Java 哈希集和树集

Java hashset and treeset

我有一个问题。它说 java 中的 hashset 不维护订单但查看我的程序

public static void main(String[] args) {
    HashSet<Integer> io=new HashSet<Integer>();

    Integer io1=new Integer(4);
    Integer io2=new Integer(5);
    Integer io3=new Integer(6);

    io.add(io2);
    io.add(io3);
    io.add(io1);

    System.out.println(io);
}

并执行它,每次我 运行 它都会给我一个有序集。为什么会这样?

另一个问题是:如果我实现一个树集(就像我在之前的程序中所做的那样,而不是使用树集的哈希集和使用我的 class 的 Integer 的 intead)我必须实现 compareto 吗?

根据oracle docs,无法保证您会一直收到相同的订单。

This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.

HashSet 不保持顺序,但它必须在打印元素时按某种顺序遍历元素。 HashSetHashMap 支持,它按照存储元素的 bin 的顺序遍历元素。在您的简单示例中,4、5、6 映射到 bin 4、5、6(因为整数的 hashCode 是整数的值)所以它们按升序打印。

如果您尝试添加 40、50、60,您会看到不同的顺序 ([50, 40, 60]),因为默认的初始 bin 数量是 16,所以哈希码 40、50、60 将是映射到 bins 40%16 (8),50%16 (2) ,60%16 (12),所以 50 是迭代的第一个元素,然后是 50 和 60。

至于 TreeSet<SomeCostumClass>,您可以在 SomeCostumClass 中实现 Comparable<SomeCostumClass>,或者将 Comparator<SomeCostumClass> 传递给构造函数。

A HashSet 保留一个内部散列 table (https://en.wikipedia.org/wiki/Hash_table),它由各个对象 hashCode() 的结果驱动。对于大多数对象,hashCode() 函数是确定性的,因此对相同元素迭代 HashSet 的结果可能是相同的。这并不意味着它将被订购。但是,对于 Integer 具体而言,函数 returns 的 hashCode() 本身就是整数,因此,对于单级散列 table 它将被排序。