使用HashMap时的奇怪行为

时间:2015-10-30 06:03:09

标签: java hashmap treemap

我正在尝试修改一个代码,我不能在这里发布,所以我在这里有一个修剪过的版本。

使用HashMap时,我的输出不稳定。

HashMap<Integer, String> test= new HashMap<>(); 
test.put(1, "one");
test.put(2, "one");
test.put(3, "one"); 
test.put(4,"four");
test.put(5, "one");
test.put(6, "one");
test.put(10, "one");
test.put(19, "one");    
test.put(20, "Sixteen");    
System.out.println(test);


HashMap<Integer, String> test3= new HashMap<>(200); 
test3.put(1, "one");
test3.put(2, "one");
test3.put(3, "one");    
test3.put(4,"four");
test3.put(5, "one");
test3.put(6, "one");
test3.put(10, "one");
test3.put(19, "one");   
test3.put(20, "Sixteen");
System.out.println(test3);  

输出

test --> {1=one, 19=one, 2=one, 3=one, 4=four, 20=Sixteen, 5=one, 6=one, 10=one}
test3--> {1=one, 2=one, 3=one, 4=four, 5=one, 6=one, 10=one, 19=one, 20=Sixteen}---> My desired output. 

即使输入值相同,为什么结果也不同。这种排序有何不同,即元素的存储?

我无法使用第二种方法,因为大小是动态的,它会根据应用程序不断变化。我是否可以使用TreeMap并获得所有值的一致输出。

7 个答案:

答案 0 :(得分:5)

当大小不同时为什么输出不同 -

这是因为在调用hashmap的put方法时,会调用hashFor(hash,table.length)。 Table.length是不同的,这意味着默认值是16,但对于你的第二种方式,大小是200.所以索引将是不同的。

请在此article

中阅读更多内容

我可以使用TreeMap,并为所有值获得一致的输出。

在Treemap保证中,将订购密钥,因此您将获得{1=one, 2=one, 3=one, 4=four, 5=one, 6=one, 10=one, 19=one, 20=Sixteen}

如果要按照插入的方式检索

,可以使用LinkedHashmap

答案 1 :(得分:2)

使用HashMaps有一个称为加载因子的概念。加载因子是hashmap在调整自身大小之前的完整程度。如果加载因子为0.5(或50%),那么当hashmap达到50%容量时,它将调整自身大小以便为更多元素腾出空间。

散列图通常具有小于100%的加载因子的原因是由于元素的存储方式。生成哈希时,使用哈希函数。您正在使用的哈希函数是默认值,它基于存储的对象的equals()方法以及目前不重要的一些额外的twiddling。事实上,两个元素最终可以使用相同的哈希,它不能保证是唯一的。当您尝试使用相同的哈希值存储两个值时,它们最终会出现在相同的“桶”中。在hashmap中。这称为碰撞。当你发生碰撞时,hashmap需要一个策略来处理它。

有时策略是线性探测&#39;。这意味着,如果一个元素发生冲突,那么hashmap将逐步查看下一个桶,寻找一个空桶。

有时策略是“链接”。其中,如果元素发生碰撞,则hashmap将用链表替换现有元素,并将每个碰撞的元素放在列表中。

所有这些意味着当元素在散列映射中发生碰撞时,插入变慢,检索元素变慢。因此,为了减少冲突的可能性,hashmap根据加载因子调整自身的大小。

除此之外,正如其他人所提到的,无法保证在基本的HashMap中进行排序。你需要使用像LinkedHashMap这样的实现。

答案 2 :(得分:1)

那是因为

  

new HashMap&lt;&gt;()构造一个具有默认初始容量的空HashMap(16)

因此,它倾向于打印索引0 ---> 15的值,然后再从索引16 - > 31打印,视为0 ---> 15。

答案 3 :(得分:1)

HashMap并未将保证作为订单提供。如果要根据插入的顺序检索地图中的元素,可以使用LinkedHashMap

答案 4 :(得分:0)

来自HashMap课程的Java docs条目,

  

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

答案 5 :(得分:0)

如果您希望自然地对键进行排序,请使用TreeMap

  

地图根据其键的自然顺序排序,或者按照   比较器在地图创建时提供,具体取决于哪个   使用构造函数。

Map<Integer, String> test= new TreeMap<>(); 
test.put(1, "one");
test.put(2, "one");
test.put(3, "one"); 
test.put(4,"four");
test.put(5, "one");
test.put(6, "one");
test.put(10, "one");
test.put(19, "one");    
test.put(20, "Sixteen");    
System.out.println(test); // Output : {1=one, 2=one, 3=one, 4=four, 5=one, 6=one, 10=one, 19=one, 20=Sixteen}

答案 6 :(得分:0)

具有默认初始容量的HashMap(16)

{1 =一,2 =一,3 =一,4 =四,5 =一,6 =一,10 =一}}

{1 =一,2 =一,3 =一,4 =四,5 =一,6 =一,10 =一}}