我可以让 indexOf 以不同的方式比较对象吗?

Can I make indexOf compare objects in a different way?

我想使用 indexOf,但 List 中的对象将不是相等的对象,但它们的值相等(即它们相等但不相等)。

我想让 indexOf 以不同于 Object.equals 方法的方式进行比较。我正在考虑覆盖 equals 方法以使用我的 isEquivalent 方法,但我不确定如何做到这一点,如果可能的话。

我尝试了很多变体,但总是出现错误:

List<CustomType> items{
        @Override
        public boolean equals(Object o)
        {
             return false;
        }
    }
    = //stuff to populate it

我也看到 this answer 他们谈论 EqualityComparer 的地方 java 中有类似的东西吗?

或者有其他方法可以做到这一点吗?

覆盖自定义对象中的 equals() 和 hashcode()。如果两个对象相等,那么它们的哈希码也应该相等。

在我看来,缺少 EqualityComparer 之类的东西是标准 java 最糟糕的事情之一。这意味着如果你想在集合中使用对象,例如 ArrayListHashSet,你只能使用一种等式概念来处理方法,例如 indexOfcontains ].这非常非常烦人。它与 TreeSet 形成鲜明对比,后者更加灵活,并允许您使用 Comparator 来指定您想要的 Set.

的顺序

我建议不要覆盖 indexOf 以表示与人们期望的不同。这很可能会导致错误和混乱。此外,您可能希望在某些时候能够使用具有通常含义的 indexOf

相反,您可以编写自己的 EqualityComparer 界面

public interface EqualityComparer<E> {

    boolean areEqual(E e1, E e2);

    int hash(E e);  // Not needed for indexOf, but very useful in general
}

然后你可以这样写一个静态方法indexOf:

public static <E> int indexOf(List<? extends E> list, E item, EqualityComparer<? super E> comparer) {
    for (int i = 0; i < list.size(); i++)
        if (comparer.areEqual(list.get(i), item))
            return i;
    return -1;
}

这是我的破解方法。我使用 ArrayList 因为 List 是一个接口,您需要重写所有方法。

List<CustomType> customList = new ArrayList<CustomType>() {
    @Override
    public int indexOf(Object o) {
        if (o instanceof CustomType) {
            for (int i = 0; i < this.size(); i++) {
                CustomType c = (CustomType) o;
                if (c.isEquivalent(this.get(i))) {
                    return i;
                }
            }
        }
        return -1;
    }
};
// use indexOf like normal, but beware of side-effects as mentioned in the comments

或者

我之前在评论中想说的是,如果您覆盖 List.equals,这意味着您正在将 List 对象与另一个对象进行比较,而不是列表中的对象。要按照您的要求进行操作,您需要这样做。

class CustomType {

    public boolean isEquivalent(CustomType ct) {
        return true; // TODO: Implement this
    }

    @Override
    public boolean equals(Object obj) {
        // TODO: Implement this
        if (obj instanceof CustomType) {
            return this.isEquivalent((CustomType) obj); 
        }
        return false;
    }

    @Override
    public int hashCode() {
        return super.hashCode(); // TODO: Implement this
    }
}

public static void main(String args[]) {
    List<CustomType> lst = new ArrayList<CustomType>();
    // use indexOf like normal
}