HashMap源码分析(一)--AbstractMap以及Map分析
有图可以看出,HashMap继承了AbstractMap,接入了Cloneable接口,Map接口与Serializeble接口。当然排开Cloneable用于允许拷贝,Serializeble用于允许对象的序列化,所以不需要多家赘述。剩下的就只有AbstractMap类与Map接口的分析。
一、Map接口
由于源码比较零散,所以也不截图了
Map作为一个接口,仅仅是用于完成一些初始方法的生命,主要作用还是作为向上传递的一个接口。
内置属性:
size属性(但是接口的属性默认static final);
内置方法:
isEmpty():boolean,判断是否为空
containKey(Object key):boolean,判断是否存在该key值
containValue(Object value):boolean,是否存在value值
get(Object key):Object,根据key值找到value
put(key,value):boolean,插入元素
putAll(Map<key,value>):boolean,插入一个Map
remove(Object key):boolean,根据key值删掉键值对
clear():boolean,清空内部
keySet():Set,取出所有key值并保存在一个set中
values():Collection,取出所有value值并存入Collection,因为value存在重复,所以不使用set
entrySet():Set<Map<k,v>>
hashcode()
equals()
内置接口:
Entry<k,y>接口:
getKey
getValue
setKey
setValue
hashcode
equals
另外就是几个比较器(比如TreeMap这种树形结构会使用,但是hashmap就不说了)
另外一些实现了方法
default V getOrDefault(Object key, V defaultValue) { V v; return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue; }
传入一个key,和一个默认的value,如果key不存在或者key对应的value为null。则获得默认的value值。否则,获得对应的value值。
default void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); for (Map.Entry<K, V> entry : entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } action.accept(k, v); } }
直接输出map内部所有对象。
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { Objects.requireNonNull(function); for (Map.Entry<K, V> entry : entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } // ise thrown from function is not a cme. v = function.apply(k, v); try { entry.setValue(v); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } } }
将
default V putIfAbsent(K key, V value) { V v = get(key); if (v == null) { v = put(key, value); } return v; }
如果key对应的value为空,则使用value代替。
default boolean remove(Object key, Object value) { Object curValue = get(key); if (!Objects.equals(curValue, value) || (curValue == null && !containsKey(key))) { return false; } remove(key); return true; }
value与key对应的value相等时或者key值存在且value不为空时,删除掉key
后续几个方法都是这种没啥意义的懒得说了。
二、AbstractMap
抽象Map基本是是对Map接口的实现,不具备太大的意义。
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; }
由于hashmap允许key和value为空,建立在key值唯一性的前提下,所以需要对于key与value进行空值判断并单独处理。
public Set<K> keySet() { if (keySet == null) { keySet = new AbstractSet<K>() { public Iterator<K> iterator() { return new Iterator<K>() { private Iterator<Entry<K,V>> i = entrySet().iterator(); public boolean hasNext() { return i.hasNext(); } public K next() { return i.next().getKey(); } 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 k) { return AbstractMap.this.containsKey(k); } }; } return keySet; }
该方法其实并没有对获得set做实现,仅仅是一个抽象的entrySet,该方法只是对于新建的KeySet的内部方法(尤其是迭代器,毕竟我们获得该set元素主要是为了迭代),clear等方法进行了重写,collection同理
public int hashCode() { int h = 0; Iterator<Entry<K,V>> i = entrySet().iterator(); while (i.hasNext()) h += i.next().hashCode(); return h; } /** * Returns a string representation of this map. The string representation * consists of a list of key-value mappings in the order returned by the * map's <tt>entrySet</tt> view's iterator, enclosed in braces * (<tt>"{}"</tt>). Adjacent mappings are separated by the characters * <tt>", "</tt> (comma and space). Each key-value mapping is rendered as * the key followed by an equals sign (<tt>"="</tt>) followed by the * associated value. Keys and values are converted to strings as by * {@link String#valueOf(Object)}. * * @return a string representation of this map */ public String toString() { Iterator<Entry<K,V>> i = entrySet().iterator(); if (! i.hasNext()) return "{}"; StringBuilder sb = new StringBuilder(); sb.append('{'); for (;;) { Entry<K,V> e = i.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append('='); sb.append(value == this ? "(this Map)" : value); if (! i.hasNext()) return sb.append('}').toString(); sb.append(',').append(' '); } }
hashcode以及equals和toString只是具体迭代相应的map对象后对map执行同样方法,而map也是找到key与value的同样方法来执行。
另外就是两个SimpleEntry的静态内部类,不太明白意义所在。