读书的时候老实说,当我们调用HashMap的put方法的时候, 同样key的值会被覆盖掉
但是 最近闲来无事研究下HashMap发现其实并不是这回事,JDK1.7以及之前对应的那个存储区域会有个LinkedList,JDK8之后换成了红黑树。 当我们put相同key的时候,会把最新的值放在那个List的第一个, 也就是说我们get到的值会是最新put进去的, 也就是老师说的“覆盖掉了”
那么这里我有个问题想请教各位大神了,既然HashMap是有这个存储机制的,那么我想请教一下, 我用什么方式可以get到这个List或者tree呢? 我看了下API, 官方并没有提供获取的方法.PS: 虽然没有实用性, 但是对那些喜欢研究原理和源代码的朋友一定是有帮助的, 所以请知道的各位朋友们和大神们踊跃发言.
但是 最近闲来无事研究下HashMap发现其实并不是这回事,JDK1.7以及之前对应的那个存储区域会有个LinkedList,JDK8之后换成了红黑树。 当我们put相同key的时候,会把最新的值放在那个List的第一个, 也就是说我们get到的值会是最新put进去的, 也就是老师说的“覆盖掉了”
那么这里我有个问题想请教各位大神了,既然HashMap是有这个存储机制的,那么我想请教一下, 我用什么方式可以get到这个List或者tree呢? 我看了下API, 官方并没有提供获取的方法.PS: 虽然没有实用性, 但是对那些喜欢研究原理和源代码的朋友一定是有帮助的, 所以请知道的各位朋友们和大神们踊跃发言.
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}
如果 key 是同一个对象,或者 equals (默认也是同一个对象为 true) 一致的话,才会覆盖。
但是是纯粹的指针性质的覆盖,没有看到楼主所说的放进一个 LinkedList (current 的是最新的、next 指向覆盖过的历史) 的逻辑。断点跟踪查看 HashMap 对象的内部结构值,也只看到了哈希值相同时的 LinkedList,没有找到楼主所说的装载覆盖历史的 LinkedList。以上红色部分,向楼主请教一下,能否解释一下?
h.put("1", "ok");
h.put("2", "No");
//当我们put相同key的时候,会把最新的值放在那个List的第一个,我用什么方式可以get到这个List或者tree呢?
Set<String> keySet = h.keySet();//这个就是楼主要的list或tree
for(String s:keySet){
System.out.println(s+"=="+h.get(s));
}
//如果不是 那么你所表达的无人能解了
throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
HashMap<String, String> map = new HashMap<>();
map.put("1234", "1234");
map.put("2345", "2345");
Field table = map.getClass().getDeclaredField("table");
table.setAccessible(true);
Object value = table.get(map); Class c2 = Class.forName("java.util.HashMap$Entry"); for(int i = 0; i < Array.getLength(value); i ++) {
Object v = Array.get(value, i);
if(v != null) {
Entry<String, String> c = (Entry<String, String>) v;
Field next = c2.getDeclaredField("next");
next.setAccessible(true);
// Object n = next.get(v);
for(; c != null; c = (Entry<String, String>)next.get(c)) {
System.out.println(c.getKey());
System.out.println(c.getValue());
}
}
}
}写了一段简陋的代码,不知道是否符合楼主的要求。