簡體   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