等于包含不同类型集合的对象

时间:2014-04-28 21:30:33

标签: java collections

我有一个看起来像这样的对象(我使用了一些Guava库来简化我的equals和hashcode方法):

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);

我遇到的问题是,即使集合的内容都是相同的,并且这些成员的编译时类型是&#34; Collection&#34;,运行时类型是用于评估相等性,因此该断言失败。查看AbstractSet.equals和AbstractList.equals的源代码,他们在评估内容之前检查另一个对象是否分别是Set或List。

我认为这是有道理的,因为订单在列表中很重要而且不在一个集合中,因此,即使内容相同,您也无法比较它们。

那就是说,在这种情况下,我并不关心底层集合是什么 - 我只是想知道内容是否相同而且顺序没有区别。有没有简单的方法呢?

2 个答案:

答案 0 :(得分:1)

如果底层集合对您无关紧要,您可以切换到一个允许重复的预定义有序集合,确保对两个新集合进行排序,然后检查是否相等。

一种简单的方法是使用toArray()将元素转换为数组,使用Arrays.sort()对其进行排序,并使用Arrays.equals()检查相等性

答案 1 :(得分:0)

就是不要这样做!由于equals的子类CollectionList以不兼容的方式定义Set,因此equals Object无法重新定义。所以唯一的可能性是坚持从integers继承的现有List,即测试参考相等。


实际上,有一个解决你的问题的方法......虽然它不是解决问题的另一个问题。如果您想将Set等于等于AbstractList(或AbstractSet,则必须选择),您可以通过简单地复制循环来编写相应的方法Comparable(或Comparator)。


如果你关心重复的元素,而不是重复的元素,你可以按照提议的方式进行复制。但是,排序需要{{1}}元素或{{1}},因此不需要应用。一个非常简单的解决方案是Guava的Multiset

然而,像你所要求的那样的东西很少出现在一个好的设计中。

通常情况更好
  • 放弃二传手
  • 添加一个类似于setter的方法,将内容复制到所需的具体集合中