HashMap源码
来源:互联网 发布:烟灶套装 知乎 编辑:程序博客网 时间:2024/06/06 04:01
1.HashMap实现了Map接口,继承AbstractMap。
初始容量,加载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中桶的数量,初始容量是创建哈希表时的容量,加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。
2.数据结构
HashMap底层实现还是数组,只是数组的每一项都是一条链表
3.源码
package java.util;import java.io.*;public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {private static final long serialVersionUID = 362498820763181265L;// 系统默认初始容量,必须是2的n次幂,这是出于优化考虑的 static final int DEFAULT_INITIAL_CAPACITY = 16;// 系统默认最大容量 static final int MAXIMUM_CAPACITY = 1 << 30;// 默认的加载因子,可在构造函数中指定 static final float DEFAULT_LOAD_FACTOR = 0.75f;// 用于存储的表,长度可以调整,且必须是2的n次幂 transient Entry[] table;// 当前map的key-value映射数,也就是当前size transient int size;// 阈值,当HashMap当前size到达这个阈值时,HashMap就需要扩大一倍了。 int threshold;// 加载因子,final常量,只能被赋值一次,赋值后值不再改变。 final float loadFactor;// 用于确保使用迭代器的时候,HashMap并未进行更改 transient volatile int modCount;private transient Set<Map.Entry<K,V>> entrySet = null;/** *@param initialCapacity 初始容量 *@param loadFactor 初始加载因子 */ 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); // 寻找一个2的k次幂capacity恰好大于initialCapacity ,保证容量是2的幂 int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; this.loadFactor = loadFactor;// 设置阀值 threshold = (int)(capacity * loadFactor); table = new Entry[capacity]; init(); }/** * 创建默认加载因子0.75的HashMap */ public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); }/** * 创建默认加载因子0.75, 默认初始容量16的HashMap*/ public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); table = new Entry[DEFAULT_INITIAL_CAPACITY]; init(); }/** * 根据m创建HashMap */ public HashMap(Map<? extends K, ? extends V> m) { this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); putAllForCreate(m); }private void putAllForCreate(Map<? extends K, ? extends V> m) { for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) { Map.Entry<? extends K, ? extends V> e = i.next(); putForCreate(e.getKey(), e.getValue()); } }/** * @param key 键 * @param value 值 */ private void putForCreate(K key, V value) { int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length);// 已存在key就覆盖 for (Entry<K,V> e = table[i]; e != null; e = e.next) {// 循环链表 Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { e.value = value; return; } } createEntry(hash, key, value, i); }/** * 创建Entry,类似addEntry, 但是不需要调整表的大小 * @param hash key的哈希值 * @param key 键 * @param value 值 * @param bucketIndex entry在数组table中的索引*/ void createEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); size++; } void init() { } static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }/** * 当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小, * 那么数据在数组上分布就比较均匀,也就是说碰撞的几率小, * 相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。 * @param h key值的哈希值求hash() * @param length hashmap长度 */ static int indexFor(int h, int length) { return h & (length-1); }public void putAll(Map<? extends K, ? extends V> m) { int numKeysToBeAdded = m.size(); if (numKeysToBeAdded == 0) return; if (numKeysToBeAdded > threshold) { int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); if (targetCapacity > MAXIMUM_CAPACITY) targetCapacity = MAXIMUM_CAPACITY; int newCapacity = table.length; while (newCapacity < targetCapacity) newCapacity <<= 1; if (newCapacity > table.length) resize(newCapacity); } for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) { Map.Entry<? extends K, ? extends V> e = i.next(); put(e.getKey(), e.getValue()); } }/** * 添加一个entry * @param key 键 * @param value 值 */ public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) {// 数组索引i处Entry存在 Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {// key值存在,则覆盖,返回旧数据value V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } }// 记录hashmap被修改了 modCount++; addEntry(hash, key, value, i); return null; }/** * key值为null */private V putForNullKey(V value) { for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(0, null, value, 0); return null; }/** * 新增一个entry * @param hash key的哈希值求hash() * @param key 键 * @param value 值 * @param bucketIndex entry在数组table中的索引 */ void addEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e);// 当hashmap个数超过阀值,需要扩容 if (size++ >= threshold) resize(2 * table.length); }/** * hashmap调整大小 * @param newCapacity 新的容量大小 */ void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) {// 如果当前大小oldCapacity等于最大值,设置阀值为(2<<31 -1),返回 threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable); table = newTable; threshold = (int)(newCapacity * loadFactor);// 新阀值 }/** * 将当前table中的所有entry赋值到新newTable * @param newTable 新table */ void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K,V> e = src[j]; if (e != null) { src[j] = null;// 源table中索引j处置null do { Entry<K,V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } }public V get(Object key) { if (key == null) return getForNullKey(); int hash = hash(key.hashCode()); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } return null; }/** * 返回key=null的value */ private V getForNullKey() { for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) return e.value; } return null; }/** * 返回key值对应的Entry对象 * @param key 键 */ final Entry<K,V> getEntry(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; } public V remove(Object key) { Entry<K,V> e = removeEntryForKey(key); return (e == null ? null : e.value); } final Entry<K,V> removeEntryForKey(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> e = prev; while (e != null) { Entry<K,V> next = e.next; Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; } public int size() { return size; } public boolean isEmpty() { return size == 0; } public void clear() { modCount++; Entry[] tab = table; for (int i = 0; i < tab.length; i++) tab[i] = null; size = 0; } public boolean containsKey(Object key) { return getEntry(key) != null; } public boolean containsValue(Object value) {if (value == null)return containsNullValue();Entry[] tab = table; for (int i = 0; i < tab.length ; i++) for (Entry e = tab[i] ; e != null ; e = e.next) if (value.equals(e.value)) return true;return false; } private boolean containsNullValue() {Entry[] tab = table; for (int i = 0; i < tab.length ; i++) for (Entry e = tab[i] ; e != null ; e = e.next) if (e.value == null) return true;return false; } final Entry<K,V> removeMapping(Object o) { if (!(o instanceof Map.Entry)) return null; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; Object key = entry.getKey(); int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> e = prev; while (e != null) { Entry<K,V> next = e.next; if (e.hash == hash && e.equals(entry)) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; } public Object clone() { HashMap<K,V> result = null;try {result = (HashMap<K,V>)super.clone();} catch (CloneNotSupportedException e) {// assert false;} result.table = new Entry[table.length]; result.entrySet = null; result.modCount = 0; result.size = 0; result.init(); result.putAllForCreate(this); return result; }/** * Entry对象 */ static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; /** * Creates new entry. * @param h Entry在table中的索引 * @param k 键 * @param v 值 * @param n 当前Entry的下一个Entry */ Entry(int h, K k, V v, Entry<K,V> n) { value = v; next = n; key = k; hash = h; } public final K getKey() { return key; } public final V getValue() { return value; } public final V setValue(V newValue) {V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry)o; Object k1 = getKey(); Object k2 = e.getKey(); if (k1 == k2 || (k1 != null && k1.equals(k2))) { Object v1 = getValue(); Object v2 = e.getValue(); if (v1 == v2 || (v1 != null && v1.equals(v2))) return true; } return false; } public final int hashCode() { return (key==null ? 0 : key.hashCode()) ^ (value==null ? 0 : value.hashCode()); } public final String toString() { return getKey() + "=" + getValue(); } /** * This method is invoked whenever the value in an entry is * overwritten by an invocation of put(k,v) for a key k that's already * in the HashMap. */ void recordAccess(HashMap<K,V> m) { } /** * This method is invoked whenever the entry is * removed from the table. */ void recordRemoval(HashMap<K,V> m) { } }/** * key值的集合 */ public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); } private final class KeySet extends AbstractSet<K> { public Iterator<K> iterator() { return newKeyIterator(); } public int size() { return size; } public boolean contains(Object o) { return containsKey(o); } public boolean remove(Object o) { return HashMap.this.removeEntryForKey(o) != null; } public void clear() { HashMap.this.clear(); } } Iterator<K> newKeyIterator() { return new KeyIterator(); } private final class KeyIterator extends HashIterator<K> { public K next() { return nextEntry().getKey(); } }/** * value值的集合 */ public Collection<V> values() { Collection<V> vs = values; return (vs != null ? vs : (values = new Values())); } private final class Values extends AbstractCollection<V> { public Iterator<V> iterator() { return newValueIterator(); } public int size() { return size; } public boolean contains(Object o) { return containsValue(o); } public void clear() { HashMap.this.clear(); } } Iterator<V> newValueIterator() { return new ValueIterator(); } private final class ValueIterator extends HashIterator<V> { public V next() { return nextEntry().value; } }/** * entry对象的集合 */ public Set<Map.Entry<K,V>> entrySet() {return entrySet0(); } private Set<Map.Entry<K,V>> entrySet0() { Set<Map.Entry<K,V>> es = entrySet; return es != null ? es : (entrySet = new EntrySet()); } private final class EntrySet extends AbstractSet<Map.Entry<K,V>> { public Iterator<Map.Entry<K,V>> iterator() { return newEntryIterator(); } public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> e = (Map.Entry<K,V>) o; Entry<K,V> candidate = getEntry(e.getKey()); return candidate != null && candidate.equals(e); } public boolean remove(Object o) { return removeMapping(o) != null; } public int size() { return size; } public void clear() { HashMap.this.clear(); } }Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }/** * 继承抽象类HashIterator */private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } }/** * 迭代器抽象类 */private abstract class HashIterator<E> implements Iterator<E> {Entry<K,V> current;// current entry Entry<K,V> next;// next entry to return int expectedModCount;// For fast-fail int index;// current slot HashIterator() {// 期望值,当一个线程在调用hashmap时,另一个线程修改了hashmap,这时modCount改变了 expectedModCount = modCount; if (size > 0) { // advance to first entry Entry[] t = table;/** * 找到数组中第一个不是指向null的那个元素,将这个元素存入next中, * 同时index指向这个数组元素的下一个下标 */ while (index < t.length && (next = t[index++]) == null); } } public final boolean hasNext() { return next != null; }/** * 首先查看当前“链表”是否已到结尾, * 若还没到,则next直接指向它的下一个”结点“; * 若已到”链表“结尾,则需要找到table数组中下一个不是指向空”链表“的那个元素,使next更新为”链表“首结点,同时更新index。 */final Entry<K,V> nextEntry() {/** * 判断HashMap是否在内部或被其它线程修改,如果modCount和expectedModCount值不一样, * 证明有其他线程在修改HashMap的结构,会抛出异常 * 所以HashMap的put、remove等操作都有modCount++的计算。 */if (modCount != expectedModCount) throw new ConcurrentModificationException();Entry<K,V> e = next;if (e == null)throw new NoSuchElementException();if ((next = e.next) == null) {// 链表到尾了Entry[] t = table;while (index < t.length && (next = t[index++]) == null);}current = e;return e;} public void remove() { if (current == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null;// HashMap.this是HashIterator外围类的引用 HashMap.this.removeEntryForKey(k); expectedModCount = modCount; } }/** * 输出到对象输出流s中 */ private void writeObject(java.io.ObjectOutputStream s) throws IOException {Iterator<Map.Entry<K,V>> i = (size > 0) ? entrySet0().iterator() : null;// 将当前类的非静态和非瞬态字段(阀值threshold,加载因子loadfactor)写入此流s.defaultWriteObject();// 写入table的大小s.writeInt(table.length);// 写入entry的个数s.writeInt(size); // Write out keys and values (alternating)if (i != null) {while (i.hasNext()) {Map.Entry<K,V> e = i.next();s.writeObject(e.getKey());s.writeObject(e.getValue());} } }/** * 从对象输入流s重新构建 */ private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {// 读入阈值threshold,加载因子loadfactor和任何隐藏的东西s.defaultReadObject();// 读取table的数量numBuckets并分配table阵列;int numBuckets = s.readInt();table = new Entry[numBuckets];// 用于子类重写 init();// 读取entry的个数int size = s.readInt();// Read the keys and values, and put the mappings in the HashMapfor (int i=0; i<size; i++) {K key = (K) s.readObject();V value = (V) s.readObject();putForCreate(key, value);} } // These methods are used when serializing HashSets int capacity() { return table.length; } float loadFactor() { return loadFactor; }}
0 0
- HashMap源码
- HashMap源码
- HashMap源码
- hashmap 源码
- HashMap源码
- HashMap源码
- HashMap源码
- HashMap源码
- HashMap源码
- 【源码】HashMap源码剖析
- 【源码】HashMap源码剖析
- 源码分析:HashMap
- 源码分析:HashMap
- HashMap源码分析
- HashMap 源码分析
- HashMap源码分析
- hashmap 源码阅读
- HashMap LinkedHashMap源码分析
- React学习之最近公共组件(九)
- 《设计模式》-- 门面模式
- MVC,MVP 和 MVVM 的图示
- windows系统和linux虚拟机共享文件
- python的import __future__作用
- HashMap源码
- dom 节点查找
- matlab 并行计算使用心得 (不断补充)
- 被误解的MVC和被神化的MVVM
- jQuery事件绑定,解绑方式
- poj2479最大数的和
- 多线程_线程的状态转换图及常见执行情况
- 获取 url 参数
- 浅谈iOS中MVVM的架构设计与团队协作