2021-10-21

java高级HashMap中的entrySet()方法的理解

基础使用:
HashMap集合中的entrySet()方法可以得到各个键值对映射关系的集合。
然后在Map.Entry中包含了getKey()和getValue()方法获取键和值。

示例:

public class Demo {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();
        map.put("abc","123");
        map.put("efg", "456");
        //使用增强for遍历循环Map集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for(Map.Entry<String,String> entry : entrySet){
            System.out.println(entry.getKey()+"->"+entry.getValue());
        }
    }
}
/**
 * 打印结果:
 * abc-->123
 * efg-->456
 */

代码执行原理分析:
HashMap中的entrySet()方法返回Set<Map.Entry<String,String>>,那么为什么entrySet()方法可以得到键值对的映射集合呢?

 public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
    }

entrySet方法的方法的原理其实和keySet()方法、values()方法的原理是一样的。

分析entrySet()方法 源码:

/**
 * 该方法的返回值就是这个map中各个键值对映射关系集合
 * 1.Map中采用是Entry内部类表示一个映射项,映射项包含key和value
 * 2.Map.Entry里面包含的getKey()和getValue()方法
 * 3.static class Node<K,V> implements Map.Entry<K,V>
 */
public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
        /**
         * 代码等价于(代码复杂化)
         * Set<Map.Entry<k,v>> es = entrySet;
         * if(es==null){
         *    entrySet = new EntrySet();
         *    return  entrySet;
         * } else {
         *     return es;
         * } 
         */  
    }

我们现在看看编译后的字节码文件Demo.class文件:

public class Demo {
    public Demo() {
    }

    public static void main(String[] args) {
        Map<String, String> map = new HashMap();
        map.put("abc", "123");
        map.put("efg", "456");
        Set<Entry<String, String>> entrySet = map.entrySet();
        Iterator var3 = entrySet.iterator();

        while(var3.hasNext()) {
            Entry<String, String> entry = (Entry)var3.next();
            PrintStream var1 = System.out;
            String var1 = (String)entry.getKey();
            var1.println(var1 + "->" + (String)entry.getValue());
        }

    }
}
/**
 * 注意到entrySet调用了iterator()方法、生成的迭代器对象var3 它调用了hasNext()和next()方法
 */

能够获取元素是通过迭代器的遍历得来的,所以entrySet()方法能有键值对的映射集合,是因为有iterator方法。那么我们想一下这个iterator方法是怎么来的呢?是因为entrySet()方法中使用new实例化了一个EntrySet类
2021-10-21
我们再查看EntrySet类的源码,里面有个iterator()方法字节码调用的就是这个iterator()方法
2021-10-21
在方法的return语句中又实例化了EntryIterator类作为返回值,是一个迭代器,我们现查看EntryIterator类的源码,它只有一个next方法:

final class EntryIterator extends HashIterator
        implements Iterator<Map.Entry<K,V>> {
        public final Map.Entry<K,V> next() { return nextNode(); }
    }

next()方法被调用返回的类型是Map.Entry<K,V>,而得到的结果是nextNode()方法的返回值。

 final Node<K,V> nextNode() {
            Node<K,V>[] t;
            Node<K,V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            if ((next = (current = e).next) == null && (t = table) != null) {
                do {} while (index < t.length && (next = t[index++]) == null);
            }
            return e;
        }

nextNode()方法作用就是返回下一个节点。
Node类是HashMap的静态内部类:
2021-10-21

Entry是Map的内部接口,该Entry接口有几个方法:

 interface Entry<K, V> {
       /**...*/
       K getKey();
       /**...*/
       V getValue();
       /**...*/
       V setValue(V value);
       /**...*/
       boolean equals(Object o);
       /**...*/
       int hashCode();

所以我们可以通过entry.getKey() 和 entry.getValue()方法获取到键和值。
注意:Node<K,V>是Map<K,V>的实现类

上一篇:【Win内核】从TEB到模块遍历


下一篇:Java泛型练习题