我正在阅读 Java Hashmap 文档,但我不明白这句话。
请注意,HashMap 的迭代顺序是不确定的。如果您想要确定性迭代,请使用 LinkedHashMap。
确定性是什么意思?
我正在阅读 Java Hashmap 文档,但我不明白这句话。
请注意,HashMap 的迭代顺序是不确定的。如果您想要确定性迭代,请使用 LinkedHashMap。
确定性是什么意思?
最简单的定义:
给定相同的输入,您总是得到相同的输出。
上面的意思是,迭代完全相同的 HashMap 可能在不同的时间给出不同的结果,即使你没有改变任何东西。通常这无关紧要,但如果确实如此,您应该使用 LinkedHashMap。
可以提前“确定”的顺序。
由于散列的工作方式,地图中的元素被“打乱”到任意位置。加扰位置不能轻易预先确定——它们是不可确定的——你不知道结果顺序。
简而言之:当您调用 keys()、values() 或 entrySet() 时,您会返回一个集合,您可以对其进行迭代。那句话是说你不能期望迭代器返回对象的顺序是任何特定的顺序。特别是,它可以不同于插入顺序和键值的自然排序。
如果您希望迭代器按插入顺序工作,请使用 LinkedHashMap。如果要按键值迭代,请使用 TreeMap。请注意,这两者的性能都比普通的 HashMap 稍差,因为它们都必须做额外的工作来跟踪顺序。
严格来说,HashMap 的迭代顺序几乎可以肯定不是非确定性的。就像绝大多数的计算过程一样,如果你以完全相同的方式经历它,结果将是完全相同的。一个真正的非确定性系统将包含一些外部随机元素,这在此处不太可能出现。至少在大多数情况下。
我认为它们真正的意思是仅仅因为地图包含一组特定的元素,你不应该期望当你迭代它们时它们会以特定的顺序出现。这并不意味着迭代的顺序是随机的,它只是意味着作为开发人员你不应该指望知道它是什么。
在大多数情况下,这样做的原因是对某些可能因平台和/或访问顺序而异的实现细节存在一些依赖性。而后者又可能由天生不可预测的线程调度和事件时序决定。
在大多数情况下,在任何单独的平台上和最常见的线程模型(单线程应用程序)上,如果您总是在序列 X 中插入和删除一组特定的东西,那么您总是会在序列 Y 中取出它们。就是这样Y 将完全依赖于 X,在平台上,甚至没有必要考虑它会是什么。
基本上,即使它不是随机的,也可能是随机的。
确定性:可以确定
非确定性:无法确定
这是一种算法,当给定特定输入时,将产生相同的输出。
我发现了一个很好的例子:
考虑一个购物清单:要购买的物品清单。
可以用两种方式解释:
* 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.
确定性意味着结果是可预测/可预见的。
非确定性意味着没有一个单一的结果可以让您事先弄清楚。算术表达式,如 1 + 2 或 log e,是确定性的。只有一个正确答案,您可以提前弄清楚。将一把沙子扔到空中,对于任何主要的精确度来说,每一粒沙子的落下位置实际上都是不确定的。
这可能并不完全正确,因为您可以查看底层库和 JVM 实现的源代码,并且可能有一些方法可以确定会产生的顺序。对他们来说,说“没有特定的顺序是有保证的”或类似的话可能更正确。
在这种情况下,相关的是您不能依赖排序。
这是 HashMap 的属性,其中元素的迭代顺序与插入的顺序不同,因为 HashMap 不会按顺序插入元素。因此文档中的行
非确定性意味着没有明确定义的行为。
在 HashMap 的情况下,取决于您插入元素的方式,您可能具有一种或其他迭代顺序。
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}