• TreeMap或者HashMap中的entrySet()方法


    查看entrySet()源码

        /**
         * Returns a {@link Set} view of the mappings contained in this map.
         *
         * <p>The set's iterator returns the entries in ascending key order. The
         * sets's spliterator is
         * <em><a href="Spliterator.html#binding">late-binding</a></em>,
         * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED} and
         * {@link Spliterator#ORDERED} with an encounter order that is ascending key
         * order.
         *
         * <p>The set is backed by the map, so changes to the map are
         * reflected in the set, and vice-versa.  If the map is modified
         * while an iteration over the set is in progress (except through
         * the iterator's own {@code remove} operation, or through the
         * {@code setValue} operation on a map entry returned by the
         * iterator) the results of the iteration are undefined.  The set
         * supports element removal, which removes the corresponding
         * mapping from the map, via the {@code Iterator.remove},
         * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
         * {@code clear} operations.  It does not support the
         * {@code add} or {@code addAll} operations.
         */
        public Set<Map.Entry<K,V>> entrySet() {
            EntrySet es = entrySet;  
            return (es != null) ? es : (entrySet = new EntrySet());
        }

    而从 EntrySet es = entrySet;  和三目运算中可以知道实际返回的是entrySet,在TreeMap类中可查看entrySet的源码

     private transient EntrySet entrySet; //java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。

    entrySet是一个临时变量,不参与序列化(关于序列化,我的另一篇博客会有略微提及),这里只是一个声明,没有传值

    同理也可以知道返回的是一个EntrySet数组,此EntrySet中存放的是Map.Entry<K,V>接口所指向的子类对象,查找源码

    static final class Entry<K,V> implements Map.Entry<K,V> {
            K key;
            V value;
            Entry<K,V> left;
            Entry<K,V> right;
            Entry<K,V> parent;
            boolean color = BLACK;
    
            /**
             * Make a new cell with given key, value, and parent, and with
             * {@code null} child links, and BLACK color.
             */
            Entry(K key, V value, Entry<K,V> parent) {
                this.key = key;
                this.value = value;
                this.parent = parent;
            }
    
            /**
             * Returns the key.
             *
             * @return the key
             */
            public K getKey() {
                return key;
            }
    
            /**
             * Returns the value associated with the key.
             *
             * @return the value associated with the key
             */
            public V getValue() {
                return value;
            }
    
            /**
             * Replaces the value currently associated with the key with the given
             * value.
             *
             * @return the value associated with the key before this method was
             *         called
             */
            public V setValue(V value) {
                V oldValue = this.value;
                this.value = value;
                return oldValue;
            }
    
            public boolean equals(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
    
                return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
            }
    
            public int hashCode() {
                int keyHash = (key==null ? 0 : key.hashCode());
                int valueHash = (value==null ? 0 : value.hashCode());
                return keyHash ^ valueHash;
            }
    
            public String toString() {
                return key + "=" + value;
            }
        }

    可以看见TreeMap中的内部类Entry<K,V>实现了 Map.Entry<K,V>接口,那么Entry<K,V>是 Map.Entry<K,V>的一个实现类,但是Entry<K,V>中的值是如何从外界添加进来的,继续查看源码中put方法

     public V put(K key, V value) {
            Entry<K,V> t = root;
            if (t == null) {
                compare(key, key); // type (and possibly null) check
    
                root = new Entry<>(key, value, null);
                size = 1;
                modCount++;
                return null;
            }
            int cmp;
            Entry<K,V> parent;
            // split comparator and comparable paths
            Comparator<? super K> cpr = comparator;
            if (cpr != null) {
                do {
                    parent = t;
                    cmp = cpr.compare(key, t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
            }
            else {
                if (key == null)
                    throw new NullPointerException();
                @SuppressWarnings("unchecked")
                    Comparable<? super K> k = (Comparable<? super K>) key;
                do {
                    parent = t;
                    cmp = k.compareTo(t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
            }
            Entry<K,V> e = new Entry<>(key, value, parent);
            if (cmp < 0)
                parent.left = e;
            else
                parent.right = e;
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }

    原来put方法将值存入了一个名为root的Entry<K,V>中,root是一个临时变量

     private transient Entry<K,V> root;

    那么到目前为止还是不知道Entry<K,V>的值如何传入entrySet中,继续查看源码,

     class EntrySet extends AbstractSet<Map.Entry<K,V>> {
            public Iterator<Map.Entry<K,V>> iterator() {
                return new EntryIterator(getFirstEntry());
            }
    
            public boolean contains(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
                Object value = entry.getValue();
                Entry<K,V> p = getEntry(entry.getKey());
                return p != null && valEquals(p.getValue(), value);
            }
    
            public boolean remove(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
                Object value = entry.getValue();
                Entry<K,V> p = getEntry(entry.getKey());
                if (p != null && valEquals(p.getValue(), value)) {
                    deleteEntry(p);
                    return true;
                }
                return false;
            }
    
            public int size() {
                return TreeMap.this.size();
            }
    
            public void clear() {
                TreeMap.this.clear();
            }
    
            public Spliterator<Map.Entry<K,V>> spliterator() {
                return new EntrySpliterator<K,V>(TreeMap.this, null, null, 0, -1, 0);
            }
        }
     final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> {
            EntryIterator(Entry<K,V> first) {
                super(first);
            }
            public Map.Entry<K,V> next() {
                return nextEntry();
            }
        }
     final Entry<K,V> nextEntry() {
                Entry<K,V> e = next;
                if (e == null)
                    throw new NoSuchElementException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                next = successor(e);
                lastReturned = e;
                return e;
            }
  • 相关阅读:
    箭头函数和普通函数的区别是什么?
    前端如何优化网站性能?
    instanceof原理
    call、apply区别
    函数的节流和防抖
    关于this的指向性问题
    undefined 和null的区别?
    浅谈堆和栈的理解?
    关于vue中watch和computed
    简单说一下什么是回流和重绘
  • 原文地址:https://www.cnblogs.com/uoar/p/7220479.html
Copyright © 2020-2023  润新知