迭代相同的哈希图键两次.订单保证相同吗?



如果我在自由标记中迭代地图两次,如下所示

<#list node_map?keys as node>
<th>${node}</th>
</#list>
<#list node_map?keys as node>
<th>${node}</th>
</#list>

两次迭代中键的顺序是否保证相同?本文档指出密钥的顺序是任意的。这是否意味着当我们多次迭代同一地图时,它可以改变?它还说

一些哈希保持有意义的顺序

这是什么意思?

我正在使用javaMap/HashMap来填充node_map模板变量。

来自 HashMap 文档:

此类不保证映射的顺序;特别是,它不保证顺序在一段时间内保持不变。

从理论上讲,这意味着即使您立即一个接一个地执行密钥(时间已更改(,也绝对无法保证后续迭代之间的键顺序,您也可以看到这个问题。

在实践中,在检查Java 8源代码之后,内部HashMap有一个Node<K,V>[] table数组,它在迭代期间所做的只是遍历它。因此,如果您在不对地图进行任何更改的情况下对node_map?keys进行 2 次后续调用,我可以自信地说它将按相同的顺序进行。我永远不会真正编写依赖于它的代码,因为它不受合同保证。

一些哈希保持有意义的顺序

这意味着您可以使用其他Map实现来保证一致的排序,例如TreeMapLinkedHashMap。如果你用LinkedHashMap填充node_map,那么它不仅在实践中而且在理论上都是一致的(如果你想依赖它,这是你应该做的(。

只要调用两次HashMap.keys()以相同的顺序返回键(到目前为止,在所有版本的 Java 中都是如此(,两个#list-s 将以相同的顺序打印键(假设后备Map中的键集在两者之间没有更改(。该文档只是意味着某些Map-s,特别是HashMap,就(普通(用户而言,具有随机的键顺序。

一些细节:#list?keys很简单,它们不会弄乱排序,它们只是调用适当的TemplateModel方法来列出键。ObjectWrapper是更棘手的;这就是将Map-S 包装成TemplateModel-s 的原因。旧配置使用SimpleHash来包装Map-s,已知在某些情况下与原始Map相比会更改键顺序,但仅在创建时,而不是在以后读取时。SimpleHash将原始Map复制到内部Map,如果原始HashMap,它会将其复制到另一个HashMap,因此行为将是相似的(尽管实际的键顺序可能会有所不同(。更现代的配置使用DefaultMapAdapter,它不会改变包装Map的键顺序,因为它只是一个适配器。因此,在这种情况下,只要包装的Map始终以相同的顺序返回密钥,FreeMarker也会这样做。

最新更新