使用Object#equals(Object)
时,是否可以在本地覆盖list.contains(someObject)
?
示例:
class SomeObject {
...
private int id;
private String name;
@Overrdide
public boolean equals(Object other){
...
return this.id == other.id;
}
}
但是当我使用list.contains(someObject)
时,如果我想要另一种平等怎么办?例如,我想知道列表是否包含某个名称?是否可以匿名覆盖Object#equals(Object)
'?
更具体的解释为什么我需要它:
int objectId = ... // Some event which passes me the attribute of an object but not the object itself
现在我有List<SomeObject> someObjects
,我想知道这个列表是否包含objectId
的对象,而不必迭代它。
我能想到的一个“解决方案”是使用Map<Integer, SomeObject> mapping
然后使用someObject = mapping.get(objectId)
编辑:我的问题不重复,因为我特意要求覆盖Object#equals(Object)
。
答案 0 :(得分:16)
您可以对从列表中获取的流对象应用过滤器。过滤器采用谓词,您可以在其中设置条件。然后,您可以检查过滤的流是否为空:
list.stream().filter(e -> e.name.equals(otherName)).findAny().isPresent()
您可以按如下方式重复使用,例如:
private <T> boolean containsWithPredicate(List<T> list, Predicate<T> predicate) {
return list.stream().filter(predicate).findAny().isPresent();
}
并按如下方式调用:
boolean containsElement = containsWithPredicate(myListOfObjects,
(e -> e.name.equals(otherName)));
修改强>
通过调用Stream.anyMatch
而不是filter
然后调用findAny
,有一种更简单的方法可以完成相同的操作:
list.stream().anyMatch(predicate);
答案 1 :(得分:7)
您可以将TreeSet
与自定义Comparator
结合使用,以实现您的目标。它没有使用equals()
来表示相等,而是认为如果compare()
返回0
,则对象是相等的。
让我们说如果长度相同,我们希望所有Strings
都相等:
TreeSet<String> set = new TreeSet(new Comparator<>() {
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}
set.add("asd");
set.contains("foo"); // Returns true
这可能是一个有用的构造(也适用于TreeMap
),如果你需要有不同的&#34;相等定义&#34;对于不同时间的对象,同时仍然使用集合。
答案 2 :(得分:6)
同一个班级无法拥有多个equals
。但您可以继承您的类并覆盖hashCode()
和equals()
,然后根据您要使用的equals
使用所需的实例。
我必须说我不喜欢这样做,equals
方法应该很好地定义,在不同的场景中使用多个equals
会非常困惑。如果我需要两个不同的equals
方法,我会有完全不同的实现,而不是子类化。所以我强烈建议你重新考虑你的设计。