覆盖类外的Object#equals(Object)

时间:2016-03-24 12:33:10

标签: java equals

使用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)

3 个答案:

答案 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方法,我会有完全不同的实现,而不是子类化。所以我强烈建议你重新考虑你的设计。