一个有关HashMap取值的问题

izard999 2018-04-16 01:31:36
读书的时候老实说,当我们调用HashMap的put方法的时候, 同样key的值会被覆盖掉
但是 最近闲来无事研究下HashMap发现其实并不是这回事,JDK1.7以及之前对应的那个存储区域会有个LinkedList,JDK8之后换成了红黑树。 当我们put相同key的时候,会把最新的值放在那个List的第一个, 也就是说我们get到的值会是最新put进去的, 也就是老师说的“覆盖掉了”
那么这里我有个问题想请教各位大神了,既然HashMap是有这个存储机制的,那么我想请教一下, 我用什么方式可以get到这个List或者tree呢? 我看了下API, 官方并没有提供获取的方法.

PS: 虽然没有实用性, 但是对那些喜欢研究原理和源代码的朋友一定是有帮助的, 所以请知道的各位朋友们和大神们踊跃发言.
...全文
1324 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
galiniur0u 2018-08-17
  • 打赏
  • 举报
回复
根据楼主的描述,楼主的意思是不是要获取table这个数组?因为table就是放置相同hash值的List。

public static void hashmap()
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());
}
}
}
}

写了一段简陋的代码,不知道是否符合楼主的要求。
叫我放猪之人 2018-08-10
  • 打赏
  • 举报
回复
应该是最新的值放到每个数组槽中的链表的第一个位置,因为hashmap认为后进来的比先进来的访问的概率大,所以为了遍历的时候效率高,将后进来的放到先进来的前面
stacksoverflow 2018-07-25
  • 打赏
  • 举报
回复
看了一下,拿不到,如果能拿到的话,那就可以改变HashMap的行为了,显然设计者是不允许这样做的。
阿闰 2018-04-18
  • 打赏
  • 举报
回复
HashMap<String, String> h = new HashMap<>();
		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));
		}
		//如果不是 那么你所表达的无人能解了
oyljerry 2018-04-16
  • 打赏
  • 举报
回复
这个所谓的List等是为了应对冲突,也就是不同的key,但是他们的hash刚好相同,那么就不能直接覆盖,而是通过一个list或tree来维护所有的数据,这样查找的时候,可以根据key,找到它正确对应的value。而如果key相同,那么就是覆盖
maradona1984 2018-04-16
  • 打赏
  • 举报
回复
应该不能叫LinkedList,毕竟java有个集合的实现类叫这个,那个只是链表,而且同样的key是会被替换的,不是你所说的放在第一位,个人觉得你应该没看懂代码
oO临时工Oo 2018-04-16
  • 打赏
  • 举报
回复
JDK1.7以及之前对应的那个存储区域会有个LinkedList 表示没听懂什么是存储区域。HashMap中存储的数据对象是 HashMap$Entry<K,V>,也不是LinkedList。
Defonds 2018-04-16
  • 打赏
  • 举报
回复
特意去看了一下 jdk1.7 的 HashMap 的源码,put 方法如下:
    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。 以上红色部分,向楼主请教一下,能否解释一下?

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧