使用哈希映射时,将键均匀分布在存储桶上非常重要。
如果所有键最终都在同一个存储桶中,那么您最终会得到一个列表。
有没有一种方法可以“审核”Java 中的 HashMap,以查看键的分布情况?
我尝试对其进行子类型化并迭代Entry<K,V>[] table
,但不可见。
我尝试对其进行子类型化并迭代 Entry[] 表,但它不可见
使用反射 API!
public class Main {
//This is to simulate instances which are not equal but go to the same bucket.
static class A {
@Override
public boolean equals(Object obj) { return false;}
@Override
public int hashCode() {return 42; }
}
public static void main(String[] args) {
//Test data
HashMap<A, String> map = new HashMap<A, String>(4);
map.put(new A(), "abc");
map.put(new A(), "def");
//Access to the internal table
Class clazz = map.getClass();
Field table = clazz.getDeclaredField("table");
table.setAccessible(true);
Map.Entry<Integer, String>[] realTable = (Map.Entry<Integer, String>[]) table.get(map);
//Iterate and do pretty printing
for (int i = 0; i < realTable.length; i++) {
System.out.println(String.format("Bucket : %d, Entry: %s", i, bucketToString(realTable[i])));
}
}
private static String bucketToString(Map.Entry<Integer, String> entry) throws Exception {
if (entry == null) return null;
StringBuilder sb = new StringBuilder();
//Access to the "next" filed of HashMap$Node
Class clazz = entry.getClass();
Field next = clazz.getDeclaredField("next");
next.setAccessible(true);
//going through the bucket
while (entry != null) {
sb.append(entry);
entry = (Map.Entry<Integer, String>) next.get(entry);
if (null != entry) sb.append(" -> ");
}
return sb.toString();
}
}
最后你会在 STDOUT 中看到类似这样的内容:
Bucket : 0, Entry: null
Bucket : 1, Entry: null
Bucket : 2, Entry: Main$A@2a=abc -> Main$A@2a=def
Bucket : 3, Entry: null
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)