轻松更改 Java 中 Collections 接口中的 .contains() 方法以断言平等

Easily Change the .contains() method in the Collections interface in Java for Asserting Equality

我想知道是否有一种方法可以轻松修改 Java 中 List 界面中的“.contains()”方法,而无需创建自定义 class。例如:

在处理 java 中的数组集合时,.contains() 方法将始终 return false,因为 .contains() 方法始终使用通用的 .equals( ) 从对象 class 调用,如果比较的对象在内存中具有相同的引用,则只有 return 为真。但是,对于数组,对两个数组执行 Arrays.equals() 检查会更有用。

代码:

public class Temp {
    public static void main(String[] args) {
        int[] myIntArray = new int[] {1, 2, 3};
        List<int[]> myList = new ArrayList<>();
        myList.add(myIntArray);
        System.out.println(myList.contains(new int[] {1, 2, 3}));
    } // Output in the console: false
    // Preferred output: true
}

我知道可以通过使用 for 循环并使用 Arrays.equals() 方法遍历整个列表来轻松完成此操作,但我的目标是学习如何轻松雕刻.contains() 方法放入我需要的东西以备将来使用。非常感谢!

I am wondering if there is a way to easily modify the contains method in the List interface in Java without creating a custom class.

没有办法。 List 的标准实现的 contains 方法的行为与 List API 指定的一样;即他们使用 equals 方法。

另一方面,不难扩展 ArrayList class 并覆盖 contains 来做你想做的事。但是如果你做得对,你需要考虑你是否想要:

  • indexOflastIndexOfcontains
  • 保持一致
  • equals(Object)的语义要与之一致
  • sublist(int, int)返回列表的语义与主列表的语义一致。

没有。 contains() 除了使用 Object.equals 之外不能做任何事情,因为这是规范所要求的。

这并不是说想要包含数组的概念是不合理的;只是你不能超载现有的概念。

你可以直接创建一个静态方法:

static <T> boolean containsArray(List<? extends T[]> list, T[] query) {
  return list.stream().anyMatch(e -> Arrays.equals(e, query));
}

然后在您要调用 list.contains(query).

的地方调用它

它的优点是适用于 any 列表(带有引用类型的数组元素):您不必专门创建它,只需更新这些专门的比较。

(以上适用于任何引用类型的数组。您需要将其专门用于原始类型的数组)。

它的另一个优点是您不必处理 强调的棘手后果(例如 indexOfremove 等如何工作)。


还有另一种选择:使用支持等于 "correctly" 的列表元素类型。例如,您可以使用 Arrays.asList 包装数组以将它们存储在列表中,因此您有一个 List<List<T>> 而不是 List<T[]>.

这将是一个侵入性的更改:它需要更改整个代码中列表的类型;你没有提供任何迹象表明你的数组列表是如何被广泛使用的。