比较两个对象的不同属性集
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
,你的规则基本上被定义为Predicate
s。
例如检查是否有20
岁的人:
List<Person> persons = ...
boolean doesAnyMatch = persons.stream()
.anyMatch(p -> p.getAge() == 20);
当然,您也可以通过与现有项目进行比较的方式设置规则,更多地模仿 equals
:
p -> p.getAge() == otherPerson.getAge()
Predicate
您可以在其他地方设置所有规则,例如Predicate
s,然后使用它们。例如:
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
替换为filter
和findAny
的组合以接收实际匹配,即Person
,而不仅仅是boolean
:
Person matchingPerson = persons.stream()
.filter(rule)
.findAny();
【讨论】:
伟大的贡献,如果多个项目可以匹配,也可以将匹配收集到一个集合中。以上是关于比较两个对象的不同属性集的主要内容,如果未能解决你的问题,请参考以下文章
Kellerman Compare .NET Objects:比较具有不同属性名称的不同类型的对象