HashMap原理分析1

1.继承关系

HashMap是继承AbstractMap抽象类,实现了Map接口,接下来先分析这几个父类:
在这里插入图片描述

1.1 Map<K,V>

map是key=value这种存储数据格式的接口,他定义了map的基本操作方法,以及存储的数据格式 Entry<k,V>
public interface Map<K,V> {

	//获取容器存的键值对数量
	int size();

 	boolean isEmpty();

	boolean containsKey(Object key);

	boolean containsValue(Object value);
	
	V get(Object key);
	
	V put(K key, V value);
	
	V remove(Object key);
	
	void putAll(Map<? extends K, ? extends V> m);
	
	void clear();
	
	//获取所有的键值对中的key,返回set
	Set<K> keySet();

	//获取所有的value,返回到Collection
	Collection<V> values();
	//注意这三个的方法,上面单个获取key或者value都是调用这个方法,这个将在
	//以后的类介绍。
	Set<Map.Entry<K, V>> entrySet();

	//同时,接口中也定义了map存储的元素类型为Entry
	interface Entry<K,V> {
      
        K getKey();

        V getValue();
     
        V setValue(V value);

        boolean equals(Object o);

        int hashCode();

        public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> c1.getKey().compareTo(c2.getKey());
        }

        public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> c1.getValue().compareTo(c2.getValue());
        }

       
        public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
        }

        public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
        }
    }
}	
	

1.2 AbstractMap<K,V>

这个抽象类是对Map接口做一个基本的实现,实现一些通用的功能,避免子类重复实现,其中有一些设计地方
需要思考下:
public abstract class AbstractMap<K,V> implements Map<K,V> {

	 //获取map中的数据,并将以Set<Entry<K,V>>形式返回,实现由子类,只需要记住功能
	 public abstract Set<Entry<K,V>> entrySet();

 	 //获取map中存入的数量,实现方式是通过调用entrySet()方法,返回的类型是Set集合,
 	 //通过Set属性来操作数据,具体的实现是在	entrySet()方法中,这个在hashmap中讲解。
 	 public int size() {
 	       return entrySet().size();
  	  }
	
	public boolean isEmpty() {
        return size() == 0;
    }	
	
	//判断map中是否存在指定key的值,可以看到,实现方式是获取到map中元素的Set,然后循环遍历
	//可知道时间复杂度是o(n),HashMap对这个进行了覆盖,是复杂度在不碰撞的情况下为o(1)
	public boolean containsKey(Object key) {
		//同样是通过这个方法,获取map中数据的set集合,进行每项循环
        Iterator<Map.Entry<K,V>> i = entrySet().iterator();
        //因为map支持存储null作为key值,所以需要分开判断,如果key为空,判断条件应该是null=e.key
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return true;
            }
        } else {
        //同样,当key不等于null时,判断条件就应该是key.equals(e.key)
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return true;
            }
        }
        return false;
    }

	//判断map中是否存在指定value的值,也是遍历map元素的set集合,HashSet虽然对这个进行了重写,但是
	//时间复杂度相差不大,因为HashMap中存储的key是可以计算出来的,但是value是杂乱的,只能通过遍历
	 public boolean containsValue(Object value) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (value==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getValue()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (value.equals(e.getValue()))
                    return true;
            }
        }
        return false;
    }

	//获取key对应的value值
	public V get(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return e.getValue();
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return e.getValue();
            }
        }
        return null;
    }
    
    //存放key,依赖具体的子类实现
	 public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
	//移除元素,根据key值,可以看到这个的实现是使用迭代器的remove函数,但是hashmap不是,
	//他重写了方法,并且在HashMap返回的entrySet()的Set集合,remove方法也被重写,是调用HashMap自身方法
	public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null;
        if (key==null) {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    correctEntry = e;
            }
        } else {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    correctEntry = e;
            }
        }

        V oldValue = null;
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();
            i.remove();
        }
        return oldValue;
    }
    
    //调用put方法,去实现复制一个map集合
	public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }
	//置空map
	 public void clear() {
        entrySet().clear();
    }

	//返回一个keyset的集合,可以看一下实现方式,返回的是一个抽象的Set对象,在里面
	//实现了他的迭代其中的方法,迭代器方法的实现也是依赖entrySet(),这个调用EntrySet()
	//获取到Set集合,然后获取Entry集合的Iterator,外部调用key的迭代器遍历时,其实内部就是在
	//调用enTrySet的迭代器,就是改写了下next()的返回值。
	public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new AbstractSet<K>() {
                public Iterator<K> iterator() {
                    return new Iterator<K>() {
                    	//获得map的元素组成的set集合的迭代器
                        private Iterator<Entry<K,V>> i = entrySet().iterator();
						
						//直接就是调用的entrySet()的迭代器方法
                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public K next() {
                        	//唯一不同之处
                            return i.next().getKey();
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

			/*********************对set集合的一些简单实现*************************/
                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object k) {
                    return AbstractMap.this.containsKey(k);
                }
            };
            keySet = ks;
        }
        return ks;
    }
	
	//和keySet()一样的思路
	public Collection<V> values() {
        Collection<V> vals = values;
        if (vals == null) {
            vals = new AbstractCollection<V>() {
                public Iterator<V> iterator() {
                    return new Iterator<V>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public V next() {
                            return i.next().getValue();
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object v) {
                    return AbstractMap.this.containsValue(v);
                }
            };
            values = vals;
        }
        return vals;
    }

	//比较方法,可以看到是比较对象,之后比较每个元素是否相同
	public boolean equals(Object o) {
        if (o == this)
            return true;

        if (!(o instanceof Map))
            return false;
        Map<?,?> m = (Map<?,?>) o;
        if (m.size() != size())
            return false;

        try {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                if (value == null) {
                    if (!(m.get(key)==null && m.containsKey(key)))
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }

        return true;
    }

}

在这里插入图片描述

通过分析得知,在抽象map中,最重要的方法时entrySet(),他是很多方法的被调用者,比如keySet(),values(),
continusKey()等,所以子类的实现这个抽象方法,并返回了Set对象,这个设计必须思考。
可以看keySet()方法,他的实现不是将从entrySet()中获取到所有Entry,取出来key存入到自己new出来的
set中,而是自己创建一个匿名的set对象,将对对象的获取通过调用entrySet()方法获取,实现更加机巧。
public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new AbstractSet<K>() {
            public Iterator<K> iterator() {
                return new Iterator<K>() {
						//
						.......迭代器实现
						//
				}
				//
				.......set抽象方法实现
				//
		}
}
这个set使用的方法也就是迭代key,所以这种实现方式返回一个set,就相当于自定义了一个set,里面的数据结构
和实现方式由自己重写,对set元素的存储不是定义一个数组或者数结构,而是让entrySet()决定,这个只负责调用就行。

上面的分析应该放在hashMap中entrySet()方法来说的,提前说,了解一下思想:

1.3 HashMap<K,V>

这里介绍HashMap与父类直接的关系,他们直接怎么设计相互调用的,具体的Hash存取值,在下一篇博客,
这个是从总体上理解HashMap的结构,为简化HashMap使用链式解决碰撞,这里简单提一下实现。
public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {
	
	//HashMap中存储的节点时Node
	static class Node<K,V> implements Map.Entry<K,V> {
		//hash设置为final,表示节点的hash值存储后是不可变的,否则找不到元素
		//因为hash的值是根据key的hashcode算出来,如果key值改变,则hash计算和存储的
		//数据就不一样,所以key值声明为不可变,hash同样不可变
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            //表示碰撞后存储的下一个节点。
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }

	/******************--method--*************************/
	//构造方法,指定加载因子,初始容量
	public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }
	
	//获取指定key元素值
	 public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }
    
	final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        //当存放节点的数组table不为空时(buckets桶)
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            //直接在数组中命中
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
                //如果是TreeNode节点,则在红黑树中查找
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                    //否则在链表中查找
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }
    
    //存放数据
	public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
	
	final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        //size表示map中的个数
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

	//扩展map容量
	final Node<K,V>[] resize() {
		//******
	}

	 /**
     * 做一下分析,上面的代码简单的说了一下的hashMap是如何存取值,实现当时是使用hash散列存储,
     * 解决碰撞冲突的方法时使用链地址法。查看下面几个方法,重写或者实现了父类的方法。
     */
	
	/*
	*这是一个唯一没有被实现的方法,HashMap的实现是先判断是否已经存在EntrySet对象,不存在则
	*创建一个新的。EntrySet是一个静态内部类
	*/
	public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
    }
	
	//查看EntrySet的实现,是不是和上面说的KeySet的实现方式是一模一样的,只是数据源上次的是
	//调用entrySet()的方法去获取,这个是调用hashmap的方法去实现。
	final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
	
		// AbstractMap 中的方法 return entrySet().size();
        public final int size()                 { return size; }
        
        // AbstractMap 中的方法 就是清空enteySet返回的set集合
        public final void clear()               { HashMap.this.clear(); }

		//下面重点讲解
        public final Iterator<Map.Entry<K,V>> iterator() {
            return new EntryIterator();
        }
		
        public final boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
            Object key = e.getKey();
            //通过调用getNode()方法实现了检测Set中是否存在元素,类似以重新创建了一个新的Set子类。
            Node<K,V> candidate = getNode(hash(key), key);
            return candidate != null && candidate.equals(e);
        }
        //remove通过调用hashmap的remove方法。
        public final boolean remove(Object o) {
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>) o;
                Object key = e.getKey();
                Object value = e.getValue();
                return removeNode(hash(key), key, value, true, true) != null;
            }
            return false;
        }
        
      /*  public final Spliterator<Map.Entry<K,V>> spliterator() {
            return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
        }
        public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
            Node<K,V>[] tab;
            if (action == null)
                throw new NullPointerException();
            if (size > 0 && (tab = table) != null) {
                int mc = modCount;
                for (int i = 0; i < tab.length; ++i) {
                    for (Node<K,V> e = tab[i]; e != null; e = e.next)
                        action.accept(e);
                }
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }*/
    }
}

上面的分析中,我们已经能够看到了一些AbstractMap的基本实现方式,子类必须实现定义的抽象方法,父类
依靠这些由子类具体实现的方法,完成操作。
下面看一下对于AbstractMap中的containsKey如何实现的:

public boolean containsKey(Object key) {
    Iterator<Map.Entry<K,V>> i = entrySet().iterator();
    if (key==null) {
       // ...
    } else {
        // ....
    }
    return false;
}
通过代码很明显就是通过调用子类实现的entrySet(),返回一个Set,调用迭代器方法,去遍历里面的数据,
去检测数据。仔细想一下,我们学习了HashMap的entrySet() 方法,知道实现是创建匿名Set,创建了一个新的
set对象,但是这个对象中,只有一些size()等方式,却没有迭代器,所以肯定要创建迭代器方法。在想一下,
hashmap的存储是Hash散列表,迭代器是顺序遍历所有元素,肯定涉及到HashMap的遍历,看一下实现:

同样还在HashMap类中,在entrySet方法中创建的自定义EntrySet类中,对Iterator的返回:


final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public final int size()                 { return size; }
        public final void clear()               { HashMap.this.clear(); }
        
        //就是创建迭代器对象
        public final Iterator<Map.Entry<K,V>> iterator() {
            return new EntryIterator();
        }
}
//HashMap中的内部类,实现了Iterator泛型是Entry(重要),继承了HashIterator
//只实现了next接口,返回当前迭代到的元素是Entry,试下关键还在于HashIterator
final class EntryIterator extends HashIterator
        implements Iterator<Map.Entry<K,V>> {
        
        public final Map.Entry<K,V> next() {
        	 return nextNode(); 
         }
    }

//是抽象内部类,是Iterator的通用实现,为什么说通用,因为需要迭代的有三个,分别是KeySet返回K的迭代器
//values返回V的迭代器,还有一个entrySet返回一个Entry<K,V>的迭代器,而这三个的元素获取,有无元素是
//一样的。
abstract class HashIterator {
        Node<K,V> next;        // next entry to return
        Node<K,V> current;     // current entry 
        int expectedModCount;  // for fast-fail
        int index;             // current slot 表示tab的下标

        HashIterator() {
            expectedModCount = modCount;
            Node<K,V>[] t = table;
            current = next = null;
            index = 0;
            //创建时,寻找到数组中第一个元素
            if (t != null && size > 0) { // advance to first entry
                do {} while (index < t.length && (next = t[index++]) == null);
            }
        }

        public final boolean hasNext() {
            return next != null;
        }

		//下一个节点元素就是,如果是
        final Node<K,V> nextNode() {
            Node<K,V>[] t;
            Node<K,V> e = next;
            if (modCount != expectedModCount)//fast - fali
                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;
        }

        public final void remove() {
            Node<K,V> p = current;
            if (p == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            current = null;
            K key = p.key;
            removeNode(hash(key), key, null, false, false);
            expectedModCount = modCount;
        }
    }

可以看出在内部类EntrySet实现了Iterator接口,内部自定义实现了迭代器获取元素。有这种需要的方法还有:

	//获取keySet的集合
	public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }
    
    //获取valueSet的集合
	public Collection<V> values() {
        Collection<V> vs = values;
        if (vs == null) {
            vs = new Values();
            values = vs;
        }
        return vs;
    }
/*******创建的内部类***********/

final class KeySet extends AbstractSet<K> {
        public final int size()                 { return size; }
        public final void clear()               { HashMap.this.clear(); }
        public final Iterator<K> iterator()     { return new KeyIterator(); }
        public final boolean contains(Object o) { return containsKey(o); }
        public final boolean remove(Object key) {
            return removeNode(hash(key), key, null, false, true) != null;
        }
        public final Spliterator<K> spliterator() {
            return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
        }
        public final void forEach(Consumer<? super K> action) {
            Node<K,V>[] tab;
            if (action == null)
                throw new NullPointerException();
            if (size > 0 && (tab = table) != null) {
                int mc = modCount;
                for (int i = 0; i < tab.length; ++i) {
                    for (Node<K,V> e = tab[i]; e != null; e = e.next)
                        action.accept(e.key);
                }
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    }
}    
final class Values extends AbstractCollection<V> {
        public final int size()                 { return size; }
        public final void clear()               { HashMap.this.clear(); }
        public final Iterator<V> iterator()     { return new ValueIterator(); }
        public final boolean contains(Object o) { return containsValue(o); }
        public final Spliterator<V> spliterator() {
            return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);
        }
        public final void forEach(Consumer<? super V> action) {
            Node<K,V>[] tab;
            if (action == null)
                throw new NullPointerException();
            if (size > 0 && (tab = table) != null) {
                int mc = modCount;
                for (int i = 0; i < tab.length; ++i) {
                    for (Node<K,V> e = tab[i]; e != null; e = e.next)
                        action.accept(e.value);
                }
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    }

/**********************辅助实现的迭代器**********************/

final class KeyIterator extends HashIterator
        implements Iterator<K> {
        public final K next() { return nextNode().key; }
   }

    final class ValueIterator extends HashIterator
        implements Iterator<V> {
        public final V next() { return nextNode().value; }
    }
将上面的三个放在一起比较,比较容易看出来结构的设计;

看一下HashMap对一些方法的覆盖:

	//判定是否包含指定key,通过hash取值,复杂度o(1)
	public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }
	//置空数组,不是迭代entySet()的Set集合了
	public void clear() {
        Node<K,V>[] tab;
        modCount++;
        //将所有的数组置为空
        if ((tab = table) != null && size > 0) {
            size = 0;
            for (int i = 0; i < tab.length; ++i)
                tab[i] = null;
        }
    }
    
    //是否包含指定value值,直接遍历table数组,省去AbstractMap中通过entrySet()方法获取
    //自定义的EntrySet对象,然后获取迭代器,在进行下面的算法遍历,减去了方法之间的调用。
    public boolean containsValue(Object value) {
        Node<K,V>[] tab; V v;
        if ((tab = table) != null && size > 0) {
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next) {
                    if ((v = e.value) == value ||
                        (value != null && value.equals(v)))
                        return true;
                }
            }
        }
        return false;
    }

最后的最后,整理下HashMap的类结构:

Node   map存储的元素类型,继承Map.Entry
KeySet  自定义内部类,实现Set接口,用于存储key值集合
Values  自定义内部类,实现Set接口,用于存储value值集合
EntrySet  自定义内部类,实现Set接口,用于存储EntrySet值集合
HashIterator  抽象类迭代器,定义迭代器的通用实现
KeyIterator  key的迭代器
ValueIterator  value的迭代器
EntryIterator  EntryIterator迭代器
HashMapSpliterator
KeySpliterator
ValueSpliterator
EntrySpliterator
TreeNode
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值