[英]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.