我在下面的类中发现了 hashmap 的一些奇怪行为。
class Employee {
private String a;
private int b;
public Employee(String a, int b) {
this.a = a;
this.b = b;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + b;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (b != other.b)
return false;
return true;
}
public static void main(String[] args) {
HashMap<Employee,Integer> map = new HashMap<>();
for(int i = 0; i < 13; i++) {
map.put(new Employee( i + "", i), i + i);
}
}
}
当我使用 new Employee( "", i) 作为在 map 中存储数据的键时,它工作正常并在第 12 个节点插入后调整 map 大小。但在使用 new Employee( i+"", i) 作为键,它表现出奇怪的行为,在使用此键添加第 10 个元素时,它将 map 的大小从 16 调整为 32,在添加第 11 个元素时,它再次将 map 的大小从 32 调整为 64。 如果您发现此行为的任何原因,请提供帮助。
最佳答案
原因 - Java 8 中 HashMap 的新组织。当特定 bin 中的列表变得太长时 HashMap
将该列表迁移到树而不是链表 - 过程称为 treeifying。
TREEIFY_THRESHOLD = 8 表示当在给定的 bin 中有 8 个条目时,给定的 bin 应该将冲突值存储在二叉树中,而不是链表(从而从 O(n) 到 O(log n)。
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash);
方法 treeifyBin 将 bin 中的所有链接节点替换为哈希,除非表太小,在这种情况下它会调整表的大小;
所以在你的情况下,你得到 64 大小(此代码使大小调整两次,将选项卡大小增加到 32 和 64 (MIN_TREEIFY_CAPACITY)):
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
关于java - Java 中 HashMap 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43998333/