簡體   English   中英

等於包含不同類型集合的對象

[英]equals on objects that contain different types of collections

我有一個看起來像這樣的對象(為了簡單地使用equals和hashcode方法,我使用了一些Guava庫):

public class MyClass {
    private Collection<Integer> integers;
    private Collection<String> strings;

    // Getters and Setters...

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        MyClass that = (MyClass) o;

        return Objects.equal(integers, that.integers) &&
               Objects.equal(strings, that.strings);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(integers, strings);
    }
}

我遇到的問題是實質上執行此操作的代碼(這是典型的測試用例):

// Produce a new instance of MyClass that users ArrayLists.
MyClass expected = new MyClass();
expected.setIntegers(Arrays.asList(1, 2, 3));
expected.setStrings(Arrays.asList("a", "b"));

// I don't normally construct the actual object here, 
// but I've included the code so you get an understanding of what's happening

// Produce a new instance of MyClass that uses HashSets.
Set<Integer> someNumbers = new HashSet<Integer>();
someNumbers.add(1);
someNumbers.add(2);
someNumbers.add(3);
Set<String> someStrings = new HashSet<String>();
someStrings.add("a");
someStrings.add("b");
MyClass actual = new MyClass();
actual.setIntegers(someNumbers);
actual.setIntegers(someStrings);

assertEquals(expected, actual);

我遇到的問題是,即使集合的內容都相同並且這些成員的編譯時類型為“ Collection”,運行時類型仍用於評估相等性,因此此斷言失敗。 查看AbstractSet.equals和AbstractList.equals的源代碼,他們在評估內容之前先檢查另一個對象是Set還是List。

我想這是有道理的,因為順序在列表中很重要,而在集合中並不重要,因此,即使內容相同,也無法進行比較。

就是說,在這種情況下,我不在乎底層集合是什么-我只想知道內容是否相同且順序沒有區別。 有沒有簡單的方法可以做到這一點?

如果基礎集合對您而言無關緊要,則可以切換到一個允許重復的預定義有序集合,確保對兩個新集合進行了排序,然后檢查是否相等。

一種簡單的方法是使用toArray()將元素轉換為數組,使用Arrays.sort()對其進行Arrays.sort() ,然后使用Arrays.equals()檢查是否相等。

只是不要這樣做! 對於Collection ,不可能明智地重新定義equals ,因為其子類ListSet以不兼容的方式對其進行定義。 因此,唯一的可能性是要堅持與現有equals繼承自Object ,即基准測試平等。


實際上,您的問題有一個解決方案……盡管它比解決方案更重要。 如果要在integers等於List (或Set ,必須選擇)時考慮integers等於,則可以通過簡單地從AbstractList (或AbstractSet )復制循環來編寫相應的方法。


如果您關心重復的元素,而不關心重復的元素,則可以按照提議的方式對副本進行排序。 但是,排序需要Comparable元素或Comparator ,因此不需要應用。 一個非常簡單的解決方案是Guava的Multiset

但是,您所要求的東西很少會出現在良好的設計中。 通常最好

  • 放棄二傳手
  • 添加類似setter的方法,將內容復制到所需的具體集合中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM