如果我在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模板变量。
答案 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
实现来确保一致排序,例如TreeMap
或LinkedHashMap
。如果您使用node_map
填充LinkedHashMap
,那么不仅在实践中而且在理论上也保证一致(如果您想依赖它,这就是您应该做的事情。)