我在Java版本1.7及以下的情况下使用反射来查找HashMap的当前容量。在下面的程序中,将12个唯一的人放入HashMap的一个桶中(使用相同的哈希码)。然后,我将第13个唯一的人放入相同或不同的桶中(使用相同或不同的哈希码)。在添加了第13个元素之后,在这两种情况下,HashMap会调整大小为32个桶。我理解由于负载因子为0.75和初始容量为16,HashMap在第13个元素时会调整大小为其两倍。但是,仍然有空桶可用,只有2个桶用于这13个元素。
我的问题是:
1. 我的理解是否正确?我没有犯任何错误。这是HashMap的预期行为吗? 2. 如果所有这些都正确,即使有12或11个空闲桶,为什么需要在这种情况下通过第13个元素将HashMap扩大一倍呢?调整HashMap大小不是额外的开销或昂贵的吗?在这种情况下,将第13个元素放入任何可用的桶中不是更好吗?
请注意,以上内容保留了HTML标签。
我的问题是:
1. 我的理解是否正确?我没有犯任何错误。这是HashMap的预期行为吗? 2. 如果所有这些都正确,即使有12或11个空闲桶,为什么需要在这种情况下通过第13个元素将HashMap扩大一倍呢?调整HashMap大小不是额外的开销或昂贵的吗?在这种情况下,将第13个元素放入任何可用的桶中不是更好吗?
请注意,以上内容保留了HTML标签。
public class HashMapTest {
public static void main(String[] args)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
HashMap<Person, String> hm = new HashMap<Person, String>();
for (int i = 1; i <= 12; i++) {
// 12 Entry in same bucket(linkedlist)
hm.put(new Person(), "1");
}
System.out.println("Number of Buckets in HashMap : " + bucketCount(hm));
System.out.println("Number of Entry in HashMap : " + hm.size());
System.out.println("**********************************");
// 13th element in different bucket
hm.put(new Person(2), "2");
System.out.println("Number of Buckets in HashMap : " + bucketCount(hm));
System.out.println("Number of Entry in HashMap : " + hm.size());
}
public static int bucketCount(HashMap<Person, String> h)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(h);
return table == null ? 0 : table.length;
}
}
class Person {
int age = 0;
Person() {
}
Person(int a) {
age = a;
}
@Override
public boolean equals(Object obj) {
return false;
}
@Override
public int hashCode() {
if (age != 0) {
return 1;
} else {
return age;
}
}
}
输出
Number of Buckets in HashMap : 16
Number of Entry in HashMap : 12
**********************************
Number of Buckets in HashMap : 32
Number of Entry in HashMap : 13