1、可以看到,其实当使用hashMap来put一个k-v的时候,他是把它放入到一个HashMap$Node(这里的Node其实是HashMap的内部类)里面,然后这些Node都是放在Table表里面的。对于一个HashMap$Node里面包含了 hash值、key、value、next。
2、然后可以看到,其实这边会有一个entrySet集合,里面同样有着{"no1","mark"},但其实这只是一个引用,真正存放数据的地方是上面讲到的HashMap$Node里面。
3、分析Entryset和HashMap
3.1 HashMap可以通过entrySet()的方法来得到对用的EntrySet集合,从下面图可以看到,得到的entries的类型是HashMap$EntrySet()
3.2 可以看到EntrySet也是HashMap的一个静态内部类,这个EntrySet集合,里面放的是Map.Entry这样一个数据类型。4、这个EntrySet集合,里面的数据类型是Map.Entry<k,v>,他是Map接口底下的一个接口。这一个Entry提供了两个很重要的方法,就是getKey和getValue,通过这两个方法可以很方便的对k-v进行遍历。
5、使用EntrySet<Entry<k,v>>进行遍历,现在得到了EntrySet集合之后,需要对Object先做向下转型
HashMap<Object, Object> hashMap = new HashMap<>(); hashMap.put("no1",mark); hashMap.put("no2",Li); Set<Map.Entry<Object, Object>> entries = hashMap.entrySet();//使用hashMap的entrySet方法来得到对应EntrySet集合。 for (Object obj : entries) { Map.Entry entry =(Map.Entry)obj;//使用增强for循环,需要通过向下转型来得到Map.Entry System.out.println(entry.getKey());//使用Map.Entry来使用getKey来得到当前Entry<k,v>里面的key System.out.println(entry.getValue());//使用Map.Entry来使用getValue来得到当前Entry<k,v>里面的value
6、最后可以看到Map.Entry里面的底层还是HashMap$Node,因为HashNode$Node实现了Map.Entry接口
7、最后总结:①HashMap使用put进去的k-v真正存放的地方是在HashMap$Node,这里的Node就是HashMap的内部类 tab[i] = newNode(hash, key, value, null)
②然后这些Node都是存放在HashMap的一个Node<k,v>类型的数组Table表中 transient Node<K,V>[] table
③为了方便k-v的遍历,提供了一个entrySet的方法,来使得HashMap变成一个EntrySet集合 Set<Map.Entry<Object, Object>> entries = hashMap.entrySet()
④这一个EntrySet集合,里面放的是Map.Entry<k,v>类型的数据,这个Map.Entry里面就是引用了k-v。
⑤通过Map.Entry的getKey和getValue方法可以进行遍历,但是在使用增强for循环遍历的时候,需要先将Object类进行向下转型得到Map.Entry类型的entry,最后使用getKey和getValue方法进行遍历,
⑥至于为什么可以这样使用,因为hashMap$Node实现了Map.Entry这个接口,可以通过getClass()来看到,其实实际上就是hashMap$Node类型 static class Node<K,V> implements Map.Entry<K,V>。