微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

比较两个对象的不同属性集

如何解决比较两个对象的不同属性集

我有一个数据类。字段可以是集合、原语、引用等。我必须检查这个类的两个实例的相等性。通常我们会为此目的重写 equals 方法。但是用例是这样的,要比较的属性可能会有所不同。

所以说,A 类有属性

int name:
int age:
List<String> hobbies;

在一次调用中,我可能必须根据姓名、年龄检查相等性,而对于另一次调用,我可能必须检查姓名、爱好的相等性

实现这一目标的最佳做法是什么?

解决方法

假设您想总是通过 2 个属性进行比较,那么在 Java 8 中最好使用一等函数。

private boolean equalNameAndAge(A a1,A a2) {
    return compareByTwoParameters(a1,a2,A::getName,A::getAge);
}

private boolean equalNameAndHobbies(A a1,A::getHobbies);
}

private boolean compareByTwoParameters(A a1,A a2,Function<A,?>... functions) {
    if (a1 == null || a2 == null) {
        return a1 == a2;
    }
    for (Function<A,?> function : functions) {
        if (!Objects.equals(function.apply(a1),function.apply(a2))) {
            return false;
        }
    }
    return true;
}
,

anyMatch

您可以使用 Stream API 解决这个问题,使用 anyMatch,您的规则基本上被定义为 Predicate

例如检查是否有人是 20 岁:

List<Person> persons = ...

boolean doesAnyMatch = persons.stream()
    .anyMatch(p -> p.getAge() == 20);

您当然也可以通过与现有项目进行比较的方式来设置规则,更多地模仿 equals

p -> p.getAge() == otherPerson.getAge()

Predicate

您可以在其他地方设置所有规则,作为 Predicate 并使用它们。例如:

List<Predicate<Person>> rules = List.of(
    p -> p.getAge() == 20,p -> p.getName().equals("John"),p -> p.getAge() > 18,p -> p.getName().length() > 10 && p.getAge() < 50
);

然后也许可以在某种循环中使用它们,无论您需要什么:

for (Predicate rule : rules) {
    boolean doesAnyMatch = persons.stream()
        .anyMatch(rule);
    ...
}

findAny

您可以将 anyMatch 替换为 filterfindAny 的组合以接收实际匹配,即 Person,而不仅仅是 boolean

Person matchingPerson = persons.stream()
    .filter(rule)
    .findAny();

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。