如何对列表执行与顺序无关的相等性检查?

mik*_*ike 5 java optimization list equals

我想在一个类上实现一个 equals 方法,其中实例的相等性是从所包含列表的“弱”相等性派生的,即不需要列表元素的相同顺序,而java.util.List.equals(Object)(您可以在下面看到它的 javadoc)要求相同的顺序。

那么,对列表执行与顺序无关的相等性检查的最佳方法是什么?


我想将列表包装到新列表中,对它们进行排序,然后在那里执行等号。

或者另一种方法(这会使这个问题过时):改用 TreeSet,这样元素的顺序在具有相等元素的集合中将始终相同。

/**
 * Compares the specified object with this list for equality.  Returns
 * <tt>true</tt> if and only if the specified object is also a list, both
 * lists have the same size, and all corresponding pairs of elements in
 * the two lists are <i>equal</i>.  (Two elements <tt>e1</tt> and
 * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
 * e1.equals(e2))</tt>.)  In other words, two lists are defined to be
 * equal if they contain the same elements in the same order.  This
 * definition ensures that the equals method works properly across
 * different implementations of the <tt>List</tt> interface.
 *
 * @param o the object to be compared for equality with this list
 * @return <tt>true</tt> if the specified object is equal to this list
 */
boolean equals(Object o);
Run Code Online (Sandbox Code Playgroud)

我知道答案并关闭了标签。之后我读了一篇关于元的文章,关于在这种情况下该怎么做。但是由于我的问题是由 SO 缓存的,所以无论如何我都会发布它。也许将来有人会遇到同样的“问题”。如果没有人发布,我将发布答案。

jar*_*bjo 5

如果您不反对添加 3rd 方库,则可以CollectionUtils.isEqualCollection(java.util.Collection a, java.util.Collection b)从 Apache Commons-Lang 使用。它本质上是比较两个任意集合(也是列表),忽略元素的顺序。

来自 API 文档:

如果给定的集合包含具有完全相同基数的完全相同的元素,则返回 true。也就是说,如果 a 中 e 的基数等于 b 中 e 的基数,对于 a 或 b 中的每个元素 e。


Cra*_*lin 2

如果您使用Eclipse Collections,则可以将两个列表都转换为 Bags,并且只需在 Bags 之间使用 equals() 即可。合同Bag.equals()是,如果两个 Bags 的每个元素数量相同,则它们是相等的,但顺序不考虑在内。这也有性能优势。toBag()Bag.equals()都是 O(n),因此此方法比对列表进行排序更快。

Assert.assertEquals(
    Lists.mutable.with(1, 2, 3, 1).toBag(),
    Lists.mutable.with(3, 2, 1, 1).toBag());
Run Code Online (Sandbox Code Playgroud)

注意:我是 Eclipse Collections 的提交者。