重写类外的对象#equals(对象)

2022-09-03 00:37:24

使用时是否可以本地覆盖 ?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> someObjectsobjectId

我能想到的一个“解决方案”是使用,然后Map<Integer, SomeObject> mappingsomeObject = mapping.get(objectId)

编辑:我的问题不是重复的,因为我特别要求覆盖。Object#equals(Object)


答案 1

您可以对从列表中获取的流对象应用筛选器。筛选器采用一个谓词,您可以在其中设置条件。然后,您可以检查过滤后的流是否不为空:

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 而不是然后执行:filterfindAny

list.stream().anyMatch(predicate);

答案 2

您可以使用带有自定义的来实现所需的内容。它不用于相等,而是考虑如果返回,对象是相等的。TreeSetComparatorequals()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


推荐