繁体   English   中英

如何在列表上执行与订单无关的相等检查?

[英]How can I perform an order-independent equality check on lists?

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

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


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

或者另一种方法(会使这个问题过时):改为使用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);

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

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

从API文档:

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

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

Assert.assertEquals(
    Lists.mutable.with(1, 2, 3, 1).toBag(),
    Lists.mutable.with(3, 2, 1, 1).toBag());

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

我可以想到几种方法来实现这一点,包括迭代列表并使用list.contains作为Sotirios在他的评论中提及。 另一种方法是使用(new HashSet(list1)).equals(new HashSet(list2)) (但这两种解决方案都会丢弃重复的条目)。

另一种包括测试重复条目等效性的方法是使用Collections.sort()来制作两个列表的排序副本,然后使用.equals()来比较这种方式。 有很多声音方法可以做到这一点,可能比我在这里提到的要多得多。

既然已经有了一些答案。 我要发帖了。

我终于使用了java.util.List.containsAll(Collection<?>) 我绊倒这种方法是我不想发布问题的原因。

@jarnbjo没有意识到你还可以考虑基数的维度!

编辑

添加了...... 修复基数问题。

  Collection<Object> a, b;

  boolean equal = (a.size() == b.size()) && a.containsAll(b);

但这也可能失败。 如果集合a具有项目x两次,集合b具有项目y两次。 然后大小相同, containsAll()得到true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM