java源碼分析之HashMap

package java.util;

import java.io.*;

/**
 * 繼承Map的抽象類AbstractMap 實現 Map(集合),Cloneable(實現對象的淺拷貝),serializable(序列化)接口,非線程安全
 * hashMap 是一個數組結構,每一個數組元素是一個鏈表,每一個鏈表中包含多個Entry類,這些Entry類的key有相同的hash值作爲數組的下標
 * created by jewhone on 2017年7月3日
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable {

	/**
	 * 默認的初始容量(必須爲2的冪)
	 * 容量爲2的n次方原因:1.不同的hash值發生碰撞的概率比較小,這樣就會使得數據在table數組中分佈較均勻,查詢速度也較快
	 */
	static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 2^4=16

	/**
	 * 最大容量爲 2^30次冪
	 */
	static final int MAXIMUM_CAPACITY = 1 << 30;

	/**
	 * 默認的負載因子爲0.75 決定何時對散列表進行再散列.例:如果負載因子是0.75, 當散列表中已經有75%的位置已經放滿,那麼將進行散列.
	 */
	static final float DEFAULT_LOAD_FACTOR = 0.75f;

	/**
	 * 空的Entry類(Entry類型的數據結構作爲內存存儲結構)
	 */
	static final Entry<?, ?>[] EMPTY_TABLE = {};

	/**
	 * HashMap是一個鏈表數組結構(包含了key,value),長度必須爲2的冪
	 */
	transient Entry<K, V>[] table = (Entry<K, V>[]) EMPTY_TABLE;

	/**
	 * 映射中包含的鍵值映射個數
	 */
	transient int size;

	/**
	 * 擴容臨界值(size>=threshold時需要擴容)(容量*負載因子)
	 */
	int threshold;

	/**
	 * 哈希表的負載因子
	 */
	final float loadFactor;

	/**
	 * 哈希表結構更改次數(遍歷時用於判斷hashmap是否被改變)
	 */
	transient int modCount;

	/**
	 * 默認的散列閾值
	 */
	static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

	/**
	 * holds values which can't be initialized until after VM is booted.
	 */
	private static class Holder {

		/**
		 * Table capacity above which to switch to use alternative hashing.
		 */
		static final int ALTERNATIVE_HASHING_THRESHOLD;

		static {
			String altThreshold = java.security.AccessController
					.doPrivileged(new sun.security.action.GetPropertyAction("jdk.map.althashing.threshold"));

			int threshold;
			try {
				threshold = (null != altThreshold) ? Integer.parseInt(altThreshold)
						: ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;

				// disable alternative hashing if -1
				if (threshold == -1) {
					threshold = Integer.MAX_VALUE;
				}

				if (threshold < 0) {
					throw new IllegalArgumentException("value must be positive integer.");
				}
			} catch (IllegalArgumentException failed) {
				throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
			}

			ALTERNATIVE_HASHING_THRESHOLD = threshold;
		}
	}

	/**
	 * 計算hash值的基礎值,保證每次hash值的唯一性
	 */
	transient int hashSeed = 0;

	/**
	 * 指定初始容量和負載因子的構造器,並初始化 預設初始容量能夠有效提高hashMap的性能(需重新計算數據位置和複製)
	 * 
	 * @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);

		this.loadFactor = loadFactor;
		threshold = initialCapacity;
		init();
	}

	/**
	 * 指定初始容量和默認的負載因子的構造器
	 *
	 * @param initialCapacity
	 *            初始容量
	 */
	public HashMap(int initialCapacity) {
		this(initialCapacity, DEFAULT_LOAD_FACTOR);
	}

	/**
	 * 默認的初始容量和負載因子的構造器
	 */
	public HashMap() {
		this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
	}

	/**
	 * 與指定Map 有相同映射的構造器
	 */
	public HashMap(Map<? extends K, ? extends V> m) {
		this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
		inflateTable(threshold);
		// 根據已有的Map 創建對應的Entry
		putAllForCreate(m);
	}

	/**
	 * 取值的大小始終爲2^n次冪(取大於指定值最近的2^n的數)
	 */
	private static int roundUpToPowerOf2(int number) {
		// assert number >= 0 : "number must be non-negative";
		int rounded = number >= MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY
				: (rounded = Integer.highestOneBit(number)) != 0
						? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded : 1;

		return rounded;
	}

	/**
	 * 擴容
	 */
	private void inflateTable(int toSize) {
		// Find a power of 2 >= toSize
		int capacity = roundUpToPowerOf2(toSize);// 指定容量值

		threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);// 指定擴容閾值
		table = new Entry[capacity];// 定義表結構
		initHashSeedAsNeeded(capacity);// 初始化hashSeed
	}

	/**
	 * 子類初始化方法
	 */
	void init() {
	}

	/**
	 * 如果哈希種子爲0且useAltHashing爲true,則根據指定capacity重置哈希種子 且只能重置一次哈希種子,這裏和虛擬機的配置有關
	 */
	final boolean initHashSeedAsNeeded(int capacity) {
		boolean currentAltHashing = hashSeed != 0;
		boolean useAltHashing = sun.misc.VM.isBooted() && (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
		boolean switching = currentAltHashing ^ useAltHashing;
		if (switching) {
			hashSeed = useAltHashing ? sun.misc.Hashing.randomHashSeed(this) : 0;
		}
		return switching;
	}

	/**
	 * hash算法,計算對象的hash值
	 */
	final int hash(Object k) {
		int h = hashSeed;
		if (0 != h && k instanceof String) {
			return sun.misc.Hashing.stringHash32((String) k);
		}

		h ^= k.hashCode();

		// 儘可能確保產生的hash值不能,減少hash碰撞的機會(approximately 8 at default load factor).
		h ^= (h >>> 20) ^ (h >>> 12);
		return h ^ (h >>> 7) ^ (h >>> 4);
	}

	/**
	 * 計算對象應該保存在數組的哪個位置(對象的hash值 和 數組長度-1 與運算)
	 */
	static int indexFor(int h, int length) {
		// assert Integer.bitCount(length) == 1 : "length must be a non-zero
		// power of 2";
		return h & (length - 1);
	}

	/**
	 * 返回Map 中鍵值對的個數.
	 */
	public int size() {
		return size;
	}

	/**
	 * 判斷 Map 是否爲空
	 */
	public boolean isEmpty() {
		return size == 0;
	}

	/**
	 * 返回指定 key鍵 對應的 value值,如果key值爲空,返回 null鍵對應的 value值
	 */
	public V get(Object key) {
		if (key == null)
			return getForNullKey();
		Entry<K, V> entry = getEntry(key);

		return null == entry ? null : entry.getValue();
	}

	/**
	 * 返回 key 爲 null 對應的鍵值
	 */
	private V getForNullKey() {
		if (size == 0) {
			return null;
		}
		// 遍歷哈希表,查找鍵爲 null 的 value值
		for (Entry<K, V> e = table[0]; e != null; e = e.next) {
			if (e.key == null)
				return e.value;
		}
		return null;
	}

	/**
	 * 判斷 Map 中是否包含指定的 key.
	 */
	public boolean containsKey(Object key) {
		return getEntry(key) != null;
	}

	/**
	 * 返回 HashMap中指定 key對應的鍵值對,若不存在,則返回null.
	 */
	final Entry<K, V> getEntry(Object key) {
		if (size == 0) {
			return null;
		}
		// 計算指定 key 的hash值
		int hash = (key == null) ? 0 : hash(key);
		// 遍歷哈希值列表,返回hash值與key的hash相等的鍵值對 key值不可重複
		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;
	}

	/**
	 * 將指定key和value保存爲鍵值對,如果 HashMap中包含 key值,則用 value 替換舊值.有返回值
	 */
	public V put(K key, V value) {
		// 如果哈希表爲空,則擴容
		if (table == EMPTY_TABLE) {
			inflateTable(threshold);
		}
		// 返回key 爲null對應的 value值,一直處於table[0].
		if (key == null)
			return putForNullKey(value);
		// 根據鍵值計算key對應的hash值
		int hash = hash(key);
		// 確定指定hash值在table中的索引位置
		int i = indexFor(hash, table.length);
		// 檢查在索引爲i的這條鏈上有沒有key重複的,有則替換原值,返回原值
		for (Entry<K, V> e = table[i]; e != null; e = e.next) {
			Object k;
			// 使用equals方法判斷是 key 的哈希值否相等
			if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
				V oldValue = e.value;
				e.value = value;
				e.recordAccess(this);
				return oldValue;// 返回舊的value.
			}
		}
		modCount++;
		// 如果在table[i]中沒找到對應的key,那麼就直接在該位置的鏈表中添加此Entry
		addEntry(hash, key, value, i);
		return null;
	}

	/**
	 * 替換原有的null鍵對應的value值,返回原有的value值
	 */
	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++;
		// 如果在table[0]中沒找到對應的key爲null,那麼就直接在該位置的鏈表中添加此Entry
		addEntry(0, null, value, 0);
		return null;
	}

	/**
	 * 更新或創建新的Entry
	 */
	private void putForCreate(K key, V value) {
		int hash = null == key ? 0 : hash(key);
		int i = indexFor(hash, table.length);

		// 在 索引爲 i 的鏈表中尋找 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;
			}
		}
		// 若在指定索引 i 的鏈表中無key值,則將其添加到鏈表中 i 位置
		createEntry(hash, key, value, i);
	}

	/**
	 * 根據已有的Map 創建對應的Entry
	 */
	private void putAllForCreate(Map<? extends K, ? extends V> m) {
		for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
			putForCreate(e.getKey(), e.getValue());
	}

	/**
	 * 用新的容量來給數組擴容。(當size達到閾值時)
	 */
	void resize(int newCapacity) {
		Entry[] oldTable = table;
		int oldCapacity = oldTable.length;
		// 如果舊數組容量等於最大容量,則將擴容臨界值增大,不進行擴容操作
		if (oldCapacity == MAXIMUM_CAPACITY) {
			threshold = Integer.MAX_VALUE;
			return;
		}

		@SuppressWarnings("rawtypes")
		Entry[] newTable = new Entry[newCapacity];
		// 將所有的鍵值對從現有的表中轉移到新表
		transfer(newTable, initHashSeedAsNeeded(newCapacity));
		table = newTable;
		threshold = (int) Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
	}

	/**
	 * 將所有的鍵值對從現有的表中轉移到新表
	 */
	void transfer(Entry[] newTable, boolean rehash) {
		int newCapacity = newTable.length;
		// 從原表中取出所有 Entry
		for (Entry<K, V> e : table) {
			// 循環將 Entry賦值給 newTable
			while (null != e) {
				Entry<K, V> next = e.next;
				if (rehash) {
					e.hash = null == e.key ? 0 : hash(e.key);
				}
				int i = indexFor(e.hash, newCapacity);
				e.next = newTable[i];// e.next爲newTable[i]保存的Entry
				newTable[i] = e;// 將e設置爲newTable[i]
				e = next;// 設置e爲下一個Entry,繼續上面while循環
			}
		}
	}

	/**
	 * 將指定Map中的所有映射覆制到現有的 HashMap中,如果指定Map中的 key鍵與現有的相同,則替換現有的key對應的value值
	 */
	public void putAll(Map<? extends K, ? extends V> m) {
		int numKeysToBeAdded = m.size();
		if (numKeysToBeAdded == 0)
			return;
		// 如果table爲空進行初始化(size*loadFactor與閾值比較)
		if (table == EMPTY_TABLE) {
			inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));
		}

		// 如果目標size 大於閾值
		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;// newCapacity 等於newCapacity 乘以2的1次方
			if (newCapacity > table.length)
				resize(newCapacity);// 重置數組容量
		}
		// 複製(將Entry依次放到新 hashMap 中)
		for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
			put(e.getKey(), e.getValue());
	}

	/**
	 * 刪除指定key對應的Entry,返回key對應的value值.
	 */
	public V remove(Object key) {
		Entry<K, V> e = removeEntryForKey(key);
		return (e == null ? null : e.value);
	}

	/**
	 * 刪除指定key對應的Entry,返回key對應的value值.
	 */
	final Entry<K, V> removeEntryForKey(Object key) {
		if (size == 0) {
			return null;
		}
		int hash = (key == null) ? 0 : hash(key);
		int i = indexFor(hash, table.length);
		Entry<K, V> prev = table[i];
		Entry<K, V> e = prev;
		// 尋找key值,刪除對應的鍵值對
		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中的第一項的引用
					table[i] = next;// 直接將第一項中的next的引用存入table[i]中
				else
					prev.next = next;// 否則將table[i]中當前Entry的前一個Entry中的next置爲當前Entry的next
				e.recordRemoval(this);
				return e;
			}
			prev = e;
			e = next;//刪除後,將後續Entry向前移一位
		}
		return e;
	}

	/**
	 * 根據Entry來刪除HashMap中的鍵值對
	 */
	final Entry<K, V> removeMapping(Object o) {
		if (size == 0 || !(o instanceof Map.Entry))
			return null;

		Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
		// 獲取Entry的鍵值
		Object key = entry.getKey();
		int hash = (key == null) ? 0 : hash(key);
		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;// 定義next 爲 e 的下一節點
			if (e.hash == hash && e.equals(entry)) {
				modCount++;
				size--;
				if (prev == e)
					table[i] = next;// 將 e 的下一節點提到鏈表頭上
				else
					prev.next = next;
				e.recordRemoval(this);
				return e;
			}
			prev = e;
			e = next;
		}

		return e;
	}

	/**
	 * 清空 hashMap 中所有的Entry.
	 */
	public void clear() {
		modCount++;
		Arrays.fill(table, null);// 將 table 中存儲的Entry全部轉爲 null
		size = 0;
	}

	/**
	 * 判斷是否有 key對應的 值爲指定的 value
	 */
	public boolean containsValue(Object value) {
		if (value == null)
			return containsNullValue();

		Entry[] tab = table;
		// 循環查詢是否有 value值爲null的鍵值對
		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;
	}

	/**
	 * 判斷是否有key 對應的value 值爲null
	 */
	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;
	}

	/**
	 * 克隆HashMap實例,這裏是淺複製,並沒有複製鍵和值的本身 (複製引用)
	 */
	public Object clone() {

		HashMap<K, V> result = null;
		try {
			// 根據原table新建了一個newTable,這說明兩個hashMap的數組不是指向的同一個對象
			result = (HashMap<K, V>) super.clone();
		} catch (CloneNotSupportedException e) {
			// assert false;
		}
		if (result.table != EMPTY_TABLE) {
			result.inflateTable(Math.min((int) Math.min(size * Math.min(1 / loadFactor, 4.0f),
					// we have limits...
					HashMap.MAXIMUM_CAPACITY), table.length));
		}
		result.entrySet = null;
		result.modCount = 0;
		result.size = 0;
		result.init();
		// 將原HashMap中存儲的元素複製到新的HashMap裏面
		result.putAllForCreate(this);

		return result;
	}

	/**
	 * Entry 單向鏈表結構 ,實現了Map.Entry接口 
	 * created by jewhone on 2017年7月4日
	 */
	static class Entry<K, V> implements Map.Entry<K, V> {
		final K key;// 鍵
		V value;// 值
		Entry<K, V> next;// 指向下一個節點
		int hash;// 哈希值

		/**
		 * 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;
		}

		/**
		 * 判斷兩個Entry是否相等,必須 key和value 值都相等,才返回true.
		 */
		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;
		}

		/**
		 * 實現hashCode
		 */
		public final int hashCode() {
			return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
		}

		public final String toString() {
			return getKey() + "=" + getValue();
		}

		/**
		 * 當向HashMap中添加元素時,即調用put(k,v)時, 
		 * 對已經在HashMap中key位置進行value的覆蓋時,會調用此方法 未做任何處理
		 */
		void recordAccess(HashMap<K, V> m) {
		}

		/**
		 * 當從HashMap中刪除了一個Entry時,會調用該函數 
		 * 未做任何處理
		 */
		void recordRemoval(HashMap<K, V> m) {
		}
	}

	/**
	 * 在指定位置添加指定hash,key,value的鍵值對
	 */
	void addEntry(int hash, K key, V value, int bucketIndex) {
		//判斷是否進行擴容
		if ((size >= threshold) && (null != table[bucketIndex])) {
			resize(2 * table.length);//2倍擴容
			hash = (null != key) ? hash(key) : 0;
			bucketIndex = indexFor(hash, table.length);//重新計算位置
		}
		//根據指定值創建一個新的Entry
		createEntry(hash, key, value, bucketIndex);
	}

	/**
	 * 在指定位置添加一個新的Entry.
	 */
	void createEntry(int hash, K key, V value, int bucketIndex) {
		Entry<K, V> e = table[bucketIndex];
		table[bucketIndex] = new Entry<>(hash, key, value, e);
		size++;
	}
	/**
	 * hashIterator實現了Iterator接口  
	 * created by jewhone on 2017年7月6日
	 */
	private abstract class HashIterator<E> implements Iterator<E> {
		Entry<K, V> next; // 下一個Entry.
		int expectedModCount; // 預期值,用於 fast-fail機制
		int index; // 當前索引
		Entry<K, V> current; // 當前 entry.
		
		//構造器
		HashIterator() {
			expectedModCount = modCount;//保存 modCount 用於 fail-fast機制
			if (size > 0) { // 先入先進原則
				Entry[] t = table;
				while (index < t.length && (next = t[index++]) == null)
					;
			}
		}
		/**
		 * 判斷是否有下一個 Entry.
		 */
		public final boolean hasNext() {
			return next != null;
		}
		/**
		 * 獲得下一個Entry.
		 */
		final Entry<K, V> nextEntry() {
			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;//當前Entry等於下一個Entry對象.
			return e;
		}
		/**
		 * 刪除Entry.
		 */
		public void remove() {
			if (current == null)
				throw new IllegalStateException();
			if (modCount != expectedModCount)
				throw new ConcurrentModificationException();
			Object k = current.key;
			current = null;
			HashMap.this.removeEntryForKey(k);
			expectedModCount = modCount;
		}
	}
	/**
	 * 內部class ValueIterator迭代器,它修改了next方法 (value)
	 * 
	 * created by jewhone on 2017年7月6日
	 */
	private final class ValueIterator extends HashIterator<V> {
		public V next() {
			return nextEntry().value;
		}
	}
	/**
	 * 內部class ValueIterator迭代器,它修改了next方法 (key)
	 * 
	 * created by jewhone on 2017年7月6日
	 */
	private final class KeyIterator extends HashIterator<K> {
		public K next() {
			return nextEntry().getKey();
		}
	}
	/**
	 * 內部class ValueIterator迭代器,它修改了next方法 (Entry)
	 * 
	 * created by jewhone on 2017年7月6日
	 */
	private final class EntryIterator extends HashIterator<Map.Entry<K, V>> {
		public Map.Entry<K, V> next() {
			return nextEntry();
		}
	}

	//定義對應上面三個的 next()方法
	Iterator<K> newKeyIterator() {
		return new KeyIterator();
	}

	Iterator<V> newValueIterator() {
		return new ValueIterator();
	}

	Iterator<Map.Entry<K, V>> newEntryIterator() {
		return new EntryIterator();
	}

	// 定義 entrySet.

	private transient Set<Map.Entry<K, V>> entrySet = null;

	/**
	 * 返回此映射中包含的 key 鍵 的 Set 視圖.(返回所有的 key值)
	 * 包含方法 size(),contains(Object o),remove(Object o),clear()
	 */
	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();
		}
	}

	/**
	 * 返回此映射中包含的 value 值 的 Collection 視圖(返回所有的 value值).
	 * 包含方法 size(),contains(Object o),clear()
	 */
	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();
		}
	}

	/**
	 * 返回此映射中包含的 Entry 的 Set 視圖(返回所有的 Entry).
	 * 包含方法 iterator(),contains(Object o),remove(Object o),size(),clear()
	 */
	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();
		}
	}

	/**
	 * 序列化
	 */
	private void writeObject(java.io.ObjectOutputStream s) throws IOException {
		// Write out the threshold, loadfactor, and any hidden stuff
		s.defaultWriteObject();

		// Write out number of buckets
		if (table == EMPTY_TABLE) {
			s.writeInt(roundUpToPowerOf2(threshold));
		} else {
			s.writeInt(table.length);
		}

		// Write out size (number of Mappings)
		s.writeInt(size);

		// Write out keys and values (alternating)
		if (size > 0) {
			for (Map.Entry<K, V> e : entrySet0()) {
				s.writeObject(e.getKey());
				s.writeObject(e.getValue());
			}
		}
	}

	private static final long serialVersionUID = 362498820763181265L;

	/**
	 * 反序列化
	 */
	private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
		// Read in the threshold (ignored), loadfactor, and any hidden stuff
		s.defaultReadObject();
		if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
			throw new InvalidObjectException("Illegal load factor: " + loadFactor);
		}

		// set other fields that need values
		table = (Entry<K, V>[]) EMPTY_TABLE;

		// Read in number of buckets
		s.readInt(); // ignored.

		// Read number of mappings
		int mappings = s.readInt();
		if (mappings < 0)
			throw new InvalidObjectException("Illegal mappings count: " + mappings);

		// capacity chosen by number of mappings and desired load (if >= 0.25)
		int capacity = (int) Math.min(mappings * Math.min(1 / loadFactor, 4.0f),
				// we have limits...
				HashMap.MAXIMUM_CAPACITY);

		// allocate the bucket array;
		if (mappings > 0) {
			inflateTable(capacity);
		} else {
			threshold = capacity;
		}

		init(); // Give subclass a chance to do its thing.

		// Read the keys and values, and put the mappings in the HashMap
		for (int i = 0; i < mappings; 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;
	}
}

總結:1.hashMap是非線程安全的,但速度快,線程安全的有 hashTable(全結構加鎖)和concurrentHashMap(分段鎖-細粒度)速度相對較慢.

     2.hashMap的同一個鏈表下 key的hash值相等,但 key值不相同. 當key值 相同,將覆蓋前面的 key對應的value值.

     3.當hashMap的容量超過了定義的大小,將產生一個兩倍於之前的數組),並根據新的 hash&(length -1)計算出新的位置,並將原有的對象放入新的數組.

     4.重新調整 hashMap 的大小可能產生競爭,在多線程的情況下會使兩個及以上的線程同時調整容量大小。一般在多線程的時候使用 hastTable 或concurrentHashMap

             5.使用 String 或 Integer類作爲 HashMap的鍵值主要是因爲其不可變性,這樣可防止放入和取出的時候key值不一致。同時也能提高查詢效率.

     6.hashMap 可以根據如下方式創建同步對象:Map m = Collections.synchronizeMap(hashMap);

     7.hashMap可以接受 key , value值爲 null,但hastTable不能.

     8. hashMap的擴容是創建一個比原來的容量更大的新數組,再重新計算 新的位置,將原來的數組元素添加到新數組中,故而相對比較浪費空間成本

     9.HashMap基於hashing原理,我們通過put()和get()方法儲存和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()              方法來計算hashcode,讓後找到bucket位置來儲存值對象。當獲取對象時,通過鍵對象的equals()方法找到正確的鍵值對,然後返回值對                  象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會儲存在鏈表的下一個節點中。 HashMap在每個鏈表節點中儲存鍵值對對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章