Java TreeSet <int []>:重复元素?

时间:2015-10-10 21:30:26

标签: java collections treeset

我希望在TreeSet中有一些int对,并按第一个数字排序。

代码test here

public static void main (String[] args) throws java.lang.Exception
{
    SortedSet<int[]> s = new TreeSet<int[]>(new Comparator<int[]>(){
        public int compare(int[] a, int[] b) {
            return b[0] - a[0];
        }
    });
    int[] a = new int[]{1, 2};
    int[] b = new int[]{1, 3};
    s.add(a);
    s.add(b);
    System.out.println(s.size());
}

我不知道为什么TreeSet的大小变成1.看起来像ab的hashCode是相同的,但为什么呢?

感谢您的帮助。

BTW:实际上,我试图将重复的数字放在一个集合中,这是不可能的。然后我尝试在一组中使用int对。第一个数字是我想要的实际数字,第二个数字是为了防止重复。但我遇到了这个问题。

2 个答案:

答案 0 :(得分:5)

结果是1,因为您的compare方法仅使用数组中的第一个数字,而您拥有的两个数组都以1开头。因此,从TreeSet的角度来看,两个数组是相同的。

TreeSet.add返回

  

如果此集合尚未包含指定的元素

,则为true

,由于这两个值被视为相等(compare返回0),因此未添加第二个值,add()返回false

答案 1 :(得分:3)

认为哈希码在基于树的数据结构中起作用是一个常见的错误,它实际上并不存在。基于哈希的集合(HashSet,LinkedHashSet,HashMap,LinkedHashMap和其他几个)使用散列和等于区分对象。

在你的情况下,一个TreeSet,你使用一个基于数组大小长度考虑相等性的比较器来处理对象相等。如果两个数组具有相同的大小,它会考虑相等。在你的情况下,数组b替换数组a在头节点中,因为两个数组的长度都是1.即使覆盖hashcode,它也不会有任何用处。

来自JavaDocs: -

请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。 (有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的。集合的行为即使其排序与equals不一致也是明确定义的;它只是不遵守Set接口的一般合同。