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

Posted

技术标签:

【中文标题】比较两个对象的不同属性集【英文标题】:Comparing two objects for varying set of properties 【发布时间】:2021-05-08 20:25:15 【问题描述】:

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

也就是说,A 类具有属性:

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

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

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

【问题讨论】:

你能完成这个例子吗? 比较是什么意思?你具体需要做什么?排序?任何可能需要Comparator 的东西?回答contains,所以基于equals?也许是完全不同的东西? 所以您只是想知道您的列表中是否有任何内容与 equality 相匹配,给定自定义规则? 长话短说,Java is missing this functionality。 @Zabuzard,对。 【参考方案1】:

假设您要始终通过 2 个属性进行比较,那么对于 Java 8,最好使用一等函数。

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


private boolean equalNameAndHobbies(A a1, A a2) 
    return compareByTwoParameters(a1, a2, A::getName, 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;

【讨论】:

我认为您应该提供更多上下文或某种迷你示例以使其完整。【参考方案2】:

anyMatch

你可以通过 Stream API 解决这个问题,使用anyMatch,你的规则基本上被定义为Predicates。

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

List<Person> persons = ...

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

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

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

Predicate

您可以在其他地方设置所有规则,例如Predicates,然后使用它们。例如:

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();

【讨论】:

伟大的贡献,如果多个项目可以匹配,也可以将匹配收集到一个集合中。

以上是关于比较两个对象的不同属性集的主要内容,如果未能解决你的问题,请参考以下文章

C# 比较两个对象的属性值是不是有改变

反射比较两个对象属性名相同值不同

Kellerman Compare .NET Objects:比较具有不同属性名称的不同类型的对象

使用 FluentAssertions 比较包含不同类型的两个字典集合

OC 对象等同性

如何在objective-c中比较两个具有很多属性的对象