Java 为什么我的程序的哈希设置顺序总是相同的?

Java 为什么我的程序的哈希设置顺序总是相同的?,java,hashset,Java,Hashset,对于一些教程,他们说: HashSet不维护任何顺序,元素将以任意随机顺序返回 但是我写了一个测试程序,结果总是一样的 import java.util.*; public class HashSetDemo { public static void main(String[] args) { HashSet<String> hs1 = new HashSet<String>(); hs1.add("a"); h

对于一些教程,他们说:

HashSet不维护任何顺序,元素将以任意随机顺序返回

但是我写了一个测试程序,结果总是一样的

import java.util.*;

public class HashSetDemo {

    public static void main(String[] args) {
        HashSet<String> hs1 = new HashSet<String>();
        hs1.add("a");
        hs1.add("b");
        hs1.add("c");
        hs1.add("d");
        hs1.add(null);
        hs1.add(null);
        System.out.println(hs1);
        System.out.println(hs1);
    }
}
我试了很多次,但顺序总是一样的。为什么?希望有人能帮助我,提前谢谢

仅仅因为他们不能保证维持秩序并不意味着他们有时会不守秩序


如果您需要订购,请使用不同的集合-例如treeset。

正如我们看到的文档

它不保证集合的迭代顺序;特别是,它不能保证订单在一段时间内保持不变


它可以维持,但不能保证。在添加、删除几次之后,您可以看到差异。

当然不是随机顺序,对于某个输入,迭代器的顺序是固定的,我认为他们想说的是顺序可能与输入顺序不同。 实际上,这里的顺序取决于
String.hashCode()
String.equals()
,以及
set.add()
调用的顺序


当您调用
System.out.print(set)
时,您的意思是
System.out.print(set.toString())
,并且
set.toString()
调用set的迭代器来访问所有元素。

这种行为的原因是
HashSet
HashMap
支持,它又由
条目
-对象的
数组
支持。其中
散列
用于查找
数组的
索引
。因此,在
散列集中总是有元素的顺序(数组的顺序),您无法保证这个顺序是什么

从代码中可以看出,
HashSet
的顺序是由其元素的计算的
hashs
的顺序决定的(或至少受其影响)。然后,对于相对简单的输入(比如您的单个字符串),您可能会假设有一个严格的
散列排序
,这将为您提供一个看似自然的排序。对于更复杂的对象,以及因此更复杂的
散列
计算,
散列
将更分散,排序“更随机”

另外,正如已经指出的,“不保证排序”并不意味着“保证随机排序”


String
类的
hashcode
-方法在这里也起作用,对于单个字符
String
s,
hashcode
将只是
字符串中一个
char
int
值。由于
char
int
值是按字母顺序排列的,因此计算出的单个
char
字符串的
散列也将按字母顺序排列。

散列集不会对其进行排序,但它并不意味着必须更改顺序。如果没有添加任何内容,则没有必要更改顺序。例如,看看这个例子

hs1.add("c");
hs1.add("b");
hs1.add("d");
hs1.add("g");
hs1.add(null);
hs1.add(null);
System.out.println(hs1);
输出:
[null,b,c,d,g]

然后我们添加一个新元素并再次打印:

    hs1.add("a");
    System.out.println(hs1);
输出:
[null,a,b,c,d,g]

正如你所见,它在一定程度上改变了顺序


没有什么是可以保证的,但这并不意味着它必须改变顺序

HashSet
顺序不是随机的,它依赖于实现,实现可以自由更改。JDK 8中有一个显著的变化。因此,如果您升级到Java8,您可能会看到
HashMap
顺序发生了变化。如果您使用像IBM这样的非Oracle JDK,情况也可能有所不同。一般来说,您永远不应该依赖它,否则您的程序将来可能会崩溃。

HashSet()没有任何顺序。它也不支持输入顺序。但顺序不是随机的。即使您更改了版本并进行了升级,该版本的输出也将更改并保持不变。通过实现您的源代码,我得到了一些不同的答案,如下所示。我已经连续几次执行了这段代码,但输出是相同的

[a、b、c、d、空]


还有一件事,HashSet()不支持重复,因此,添加重复的“null”只会增加代码的长度。

HashSet
用于查找可能的重复项,并且必须在对象的哈希(
hashCode()
)之后对列表中的对象进行排序才能做到这一点。

不会,请尝试,您会看到区别;)在
HashMap
类中没有生成随机数,因此这并不令人意外。“无保证顺序”与“保证随机顺序”并不完全相同。
    hs1.add("a");
    System.out.println(hs1);