迭代相同的HashMap键两次。订单保证是否相同?

时间:2017-08-16 20:37:14

标签: html freemarker

如果我在freemarker中迭代地图两次,如下所示

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

在两次迭代中,键的顺序是否保证相同?这个documentation表示密钥的顺序是任意的。这是否意味着当我们多次迭代同一个地图时它会发生变化?它还说

  

一些哈希维持有意义的秩序

这是什么意思?

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

2 个答案:

答案 0 :(得分:1)

就被调用两次的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也会这样做。

答案 1 :(得分:1)

来自HashMap文档:

  

此课程不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。

理论上,这意味着即使您一个接一个地(时间已经改变)立即执行它们,也几乎无法保证后续迭代之间的键顺序,您还可以看到this question。< / p>

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

  

一些哈希维持有意义的秩序

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