我可以让 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 最糟糕的事情之一。这意味着如果你想在集合中使用对象,例如 ArrayList
或 HashSet
,你只能使用一种等式概念来处理方法,例如 indexOf
和 contains
].这非常非常烦人。它与 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
}
我想使用 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 最糟糕的事情之一。这意味着如果你想在集合中使用对象,例如 ArrayList
或 HashSet
,你只能使用一种等式概念来处理方法,例如 indexOf
和 contains
].这非常非常烦人。它与 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
}