36

我正在阅读 Java Hashmap 文档,但我不明白这句话。

请注意,HashMap 的迭代顺序是不确定的。如果您想要确定性迭代,请使用 LinkedHashMap。

确定性是什么意思?

4

11 回答 11

46

最简单的定义:

给定相同的输入,您总是得到相同的输出。

上面的意思是,迭代完全相同的 HashMap 可能在不同的时间给出不同的结果,即使你没有改变任何东西。通常这无关紧要,但如果确实如此,您应该使用 LinkedHashMap。

于 2010-08-25T21:40:07.983 回答
13

可以提前“确定”的顺序。

由于散列的工作方式,地图中的元素被“打乱”到任意位置。加扰位置不能轻易预先确定——它们是不可确定的——你不知道结果顺序。

于 2010-08-25T21:37:09.193 回答
8

简而言之:当您调用 keys()、values() 或 entrySet() 时,您会返回一个集合,您可以对其进行迭代。那句话是说你不能期望迭代器返回对象的顺序是任何特定的顺序。特别是,它可以不同于插入顺序和键值的自然排序。

如果您希望迭代器按插入顺序工作,请使用 LinkedHashMap。如果要按键值迭代,请使用 TreeMap。请注意,这两者的性能都比普通的 HashMap 稍差,因为它们都必须做额外的工作来跟踪顺序。

于 2010-08-25T21:40:58.387 回答
8

严格来说,HashMap 的迭代顺序几乎可以肯定不是非确定性的。就像绝大多数的计算过程一样,如果你以完全相同的方式经历它,结果将是完全相同的。一个真正的非确定性系统将包含一些外部随机元素,这在此处不太可能出现。至少在大多数情况下。

我认为它们真正的意思是仅仅因为地图包含一组特定的元素,你不应该期望当你迭代它们时它们会以特定的顺序出现。这并不意味着迭代的顺序是随机的,它只是意味着作为开发人员你不应该指望知道它是什么。

在大多数情况下,这样做的原因是对某些可能因平台和/或访问顺序而异的实现细节存在一些依赖性。而后者又可能由天生不可预测的线程调度和事件时序决定。

在大多数情况下,在任何单独的平台上和最常见的线程模型(单线程应用程序)上,如果您总是在序列 X 中插入和删除一组特定的东西,那么您总是会在序列 Y 中取出它们。就是这样Y 将完全依赖于 X,在平台上,甚至没有必要考虑它会是什么。

基本上,即使它不是随机的,也可能是随机的。

于 2010-08-25T22:18:26.657 回答
5

确定性:可以确定
非确定性:无法确定

于 2010-08-25T21:37:44.843 回答
3

这是一种算法,当给定特定输入时,将产生相同的输出。

我发现了一个很好的例子:

考虑一个购物清单:要购买的物品清单。

可以用两种方式解释:

* The instruction to buy all of those items, in any order. 
   This is a nondeterministic algorithm.
* The instruction to buy all of those items, in the order given. This is a 
   deterministic algorithm.
于 2010-08-25T21:40:24.963 回答
2

确定性意味着结果是可预测/可预见的。

于 2010-08-25T21:38:20.597 回答
2

非确定性意味着没有一个单一的结果可以让您事先弄清楚。算术表达式,如 1 + 2 或 log e,是确定性的。只有一个正确答案,您可以提前弄清楚。将一把沙子扔到空中,对于任何主要的精确度来说,每一粒沙子的落下位置实际上都是不确定的。

这可能并不完全正确,因为您可以查看底层库和 JVM 实现的源代码,并且可能有一些方法可以确定会产生的顺序。对他们来说,说“没有特定的顺序是有保证的”或类似的话可能更正确。

在这种情况下,相关的是您不能依赖排序。

于 2010-08-25T21:45:15.167 回答
0

这是 HashMap 的属性,其中元素的迭代顺序与插入的顺序不同,因为 HashMap 不会按顺序插入元素。因此文档中的行

于 2010-08-25T21:39:08.180 回答
0

非确定性意味着没有明确定义的行为。

在 HashMap 的情况下,取决于您插入元素的方式,您可能具有一种或其他迭代顺序。

于 2010-08-25T21:41:50.087 回答
-4

HashMap不维护你添加的顺序,如果你希望你的输出是你添加的顺序,你应该使用LinkedHashMap,deterministic也就是说有序地输出你添加的东西。

这是示例:1.non-deterministic

    HashMap<String, Integer> map = new HashMap<String,Integer>();
    map.put("a",5);
    map.put("b",16);
    map.put("c",46);
    System.out.println(map); //ouptput:{a=5, c=46, b=16}

2.确定性

HashMap<String, Integer> map = new LinkedHashMap<String,Integer>();
            map.put("a",5);
            map.put("b",16);
            map.put("c",46);
            System.out.println(map); //output:{a=5, b=16, c=46}
于 2010-08-26T06:42:50.970 回答