国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java集合系列——Map之HashMap介紹(八)

2019-11-06 07:45:20
字體:
供稿:網(wǎng)友

1.HashMap的簡介 (JDK1.7.0_79版本) HashMap是基于哈希表的Map實現(xiàn)的的,一個Key對應(yīng)一個Value,允許使用null鍵和null值,不保證映射的順序,特別是它不保證該順序恒久不變!也不是同步的。 怎么理解不保證恒久不變呢?

當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時的時候,哈希表進行rehash操作(即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu)),此時映射順序可能會被打亂!

HashMap存放元素是通過哈希算法將其中的元素散列的存放在各個“桶”之間。

注:HashMap除了非同步和可以使用null之外,其他的和HashTable大致相同。so ,后面就不在介紹HashTable了!

2.HashMap的繼承關(guān)系

類 HashMap<K,V>java.lang.Object 繼承者 java.util.AbstractMap<K,V> 繼承者 java.util.HashMap<K,V>類型參數(shù): K - 此映射所維護的鍵的類型 V - 所映射值的類型所有已實現(xiàn)的接口: Serializable, Cloneable, Map<K,V>

繼承AbstractMap 抽象類, AbstractMap實現(xiàn)了Map接口中的一些方法,減少了重復(fù)代碼!

實現(xiàn)了Map、Cloneable、java.io.Serializable接口!

類圖關(guān)系參看上一篇的Map介紹

3.HashMap的API

HashMap API (1)構(gòu)造函數(shù):

HashMap() 構(gòu)造一個具有默認(rèn)初始容量 (16) 和默認(rèn)加載因子 (0.75) 的空 HashMap。 HashMap(int initialCapacity) 構(gòu)造一個帶指定初始容量和默認(rèn)加載因子 (0.75) 的空 HashMap。 HashMap(int initialCapacity, float loadFactor) 構(gòu)造一個帶指定初始容量和加載因子的空 HashMap。 HashMap(Map<? extends K,? extends V> m) 構(gòu)造一個映射關(guān)系與指定 Map 相同的新 HashMap。

(2)方法

void clear() 從此映射中移除所有映射關(guān)系。 Object clone() 返回此 HashMap 實例的淺表副本:并不復(fù)制鍵和值本身。 boolean containsKey(Object key) 如果此映射包含對于指定鍵的映射關(guān)系,則返回 true。 boolean containsValue(Object value) 如果此映射將一個或多個鍵映射到指定值,則返回 true。 Set<Map.Entry<K,V>> entrySet() 返回此映射所包含的映射關(guān)系的 Set 視圖。 V get(Object key) 返回指定鍵所映射的值;如果對于該鍵來說,此映射不包含任何映射關(guān)系,則返回 null。 boolean isEmpty() 如果此映射不包含鍵-值映射關(guān)系,則返回 true。 Set<K> keySet() 返回此映射中所包含的鍵的 Set 視圖。 V put(K key, V value) 在此映射中關(guān)聯(lián)指定值與指定鍵。 void putAll(Map<? extends K,? extends V> m) 將指定映射的所有映射關(guān)系復(fù)制到此映射中,這些映射關(guān)系將替換此映射目前針對指定映射中所有鍵的所有映射關(guān)系。 V remove(Object key) 從此映射中移除指定鍵的映射關(guān)系(如果存在)。 int size() 返回此映射中的鍵-值映射關(guān)系數(shù)。 Collection<V> values() 返回此映射所包含的值的 Collection 視圖。

從類 java.util.AbstractMap 繼承的方法 equals, hashCode, toString !

4.源碼

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable{ /** * 初始化容量 - 必須是2的冪。 */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 左移 相當(dāng)于 2^4 = 16 /** * 最大的容量,容量必須是 必須是2的冪 并且小于等于 2^30(1<<30). * 若容量大于該值,則由該值替換! */ static final int MAXIMUM_CAPACITY = 1 << 30; //2^30 /** * 在構(gòu)造函數(shù)中使用的加載因子(默認(rèn)加載因子為0.75) */ static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * An empty table instance to share when the table is not inflated. * 當(dāng)表的容量不增加時候共享空表的實例 */ static final Entry<?,?>[] EMPTY_TABLE = {}; /** * The table, resized as necessary. Length MUST Always be a power of two. * 表,根據(jù)需要調(diào)整大小。長度必須一致是2的冪。 */ transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE; /** * The number of key-value mappings contained in this map. * 此Map中鍵值映射的數(shù)量(大小) */ transient int size; /** * The next size value at which to resize (capacity * load factor). * 調(diào)整大小的下一個大小值(容量*負(fù)載系數(shù))。 * @serial */ // HashMap的閾值,用于判斷是否需要調(diào)整HashMap的容量(threshold = 容量*加載因子) int threshold; /** * The load factor for the hash table. * 加載因子實際大小 * @serial */ final float loadFactor; /** * 記錄HashMap結(jié)構(gòu)修改的次數(shù),用于對HashMap的集合視圖執(zhí)行故障轉(zhuǎn)移。 * 可以判斷是否要拋出 ConcurrentModificationException 異常! */ transient int modCount; /** * map容量的默認(rèn)閾值,高于該值時,對字符串鍵使用備用散列。 * 替代散列減少了由于對于字符串鍵的散列碼計算較弱而導(dǎo)致的沖突的發(fā)生率。 * * 此值可以通過定義系統(tǒng)屬性jdk.map.althashing.threshold來覆蓋。 * 屬性值1強制在所有時間使用備用散列,而-1值確保不使用備用散列。 */ static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE; /** * holds values which can't be initialized until after VM is booted. * 保存直到VM引導(dǎo)后才能初始化的值。 * 設(shè)置是否使用替代哈希 */ 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 // 如果-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; } } /** * A randomizing value associated with this instance that is applied to * hash code of keys to make hash collisions harder to find. If 0 then * alternative hashing is disabled. * 與此實例相關(guān)聯(lián)的隨機化值,應(yīng)用于密鑰的哈希碼,以使哈希碰撞更難以找到。 * 如果為0,則禁用備用散列。 */ transient int hashSeed = 0; /** * 構(gòu)造空HashMap,具有指定的初始容量和負(fù)載因子。 */ 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; //默認(rèn)加載因子為0.75 threshold = initialCapacity; //默認(rèn)初始化容量為 2^4 = 16 init(); } /** * 構(gòu)造一個帶指定初始容量和默認(rèn)加載因子 (0.75) 的空 HashMap。 */ public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } /** * 構(gòu)造一個具有默認(rèn)初始容量 (16) 和默認(rèn)加載因子 (0.75) 的空 HashMap。 */ public HashMap() { this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); } /** * 構(gòu)造一個映射關(guān)系與指定 Map 相同的新 HashMap。 */ public HashMap(Map<? extends K, ? extends V> m) { // 新的map的初始化大小 : (size / 0.75(加載因子) ) + 1 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); inflateTable(threshold);//增容的table putAllForCreate(m); } private static int roundUpToPowerOf2(int number) { // assert number >= 0 : "number must be non-negative"; return number >= MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1; } /** * Inflates the table. */ private void inflateTable(int toSize) { // Find a power of 2 >= toSize // 找到 2的冪 >= toSize int capacity = roundUpToPowerOf2(toSize); //這里判斷 capacity * loadFactor, MAXIMUM_CAPACITY + 1 取最小值 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); table = new Entry[capacity];//初始化table的容量 initHashSeedAsNeeded(capacity); } // internal utilities /** *子類初始化 */ void init() { } /** * Initialize the hashing mask value. We defer initialization until we * really need it. * 初始化散列掩碼值。 我們推遲初始化,直到我們真的需要它。 */ final boolean initHashSeedAsNeeded(int capacity) { boolean currentAltHashing = hashSeed != 0; boolean useAltHashing = sun.misc.VM.isBooted() && (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);//這里使用到了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(); // 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); } /** *返回h在數(shù)組中的索引值,這里用&代替取模,旨在提升效率 */ 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); } /** * 獲取大小 */ public int size() { return size; } /** *判斷是否為空 */ public boolean isEmpty() { return size == 0; } /** * get根據(jù)key獲取value * * 分為可以等于null和不等于null */ public V get(Object key) { if (key == null) return getForNullKey(); Entry<K,V> entry = getEntry(key);//通過key在Entry 里面查找value return null == entry ? null : entry.getValue(); } /** * 如果key 為null,判斷map的大小是否為 0 ,為0 的話,返回null * 否則去Entry里面查詢key == null,對于的Value值 */ private V getForNullKey() { if (size == 0) { return null; } for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) return e.value; } return null; } /** * 判斷Map中是否有對應(yīng)的key * 如果可以存在返回true,否則返回false */ public boolean containsKey(Object key) { return getEntry(key) != null; } /** * 返回與HashMap中的指定鍵相關(guān)聯(lián)的條目。 如果HashMap不包含鍵的映射,則返回null。 */ final Entry<K,V> getEntry(Object key) { if (size == 0) { return null; } int hash = (key == null) ? 0 : 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; } /** * 往map中添加“key-value” * */ public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null)//若key == null,將value添加到table[0] return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; //判斷之前的Entry中是否對應(yīng)的key,如果有對應(yīng)的key,那么將之前的key對應(yīng)的value進行替換 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; // 如果不存在key對應(yīng)value對,則直接添加到table[i]處! addEntry(hash, key, value, i); return null; } /** * 將“key為null”鍵值對添加到table[0]位置 */ private V putForNullKey(V value) { for (Entry<K,V> e = table[0]; e != null; e = e.next) { //判斷之前是否有key等于null,有的話,table[0]進行替換 if (e.key == null) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; // 如果不存在key為null的鍵值對,則直接添加到table[0]處! addEntry(0, null, value, 0); return null; } /** * 內(nèi)部方法。它被構(gòu)造函數(shù)等調(diào)用。創(chuàng)建HashMap對應(yīng)的“添加方法”,和put不同 。 */ private void putForCreate(K key, V value) { int hash = null == key ? 0 : hash(key); int i = indexFor(hash, table.length); 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); } private void putAllForCreate(Map<? extends K, ? extends V> m) { for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) putForCreate(e.getKey(), e.getValue()); } /** * 重新調(diào)整HashMap的大小,newCapacity是調(diào)整后的容量 */ void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; //如果容量達到最大值,不在擴容,直接返回 if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable, initHashSeedAsNeeded(newCapacity)); table = newTable; threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); } /** * 將當(dāng)前表中的所有條目添加到newTable。 */ void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K,V> e : table) { 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]; newTable[i] = e; e = next; } } } /** * 將m中的元素全部添加到HashMap中 */ public void putAll(Map<? extends K, ? extends V> m) { int numKeysToBeAdded = m.size(); if (numKeysToBeAdded == 0)//m的容量為0 ,直接返回 return; if (table == EMPTY_TABLE) { //從新設(shè)置閾值 inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold)); } /* * m的容量大于閾值,擴容 */ 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 (Map.Entry<? extends K, ? extends V> e : m.entrySet()) put(e.getKey(), e.getValue()); } /** * 刪除“鍵為key”元素 */ public V remove(Object key) { Entry<K,V> e = removeEntryForKey(key); return (e == null ? null : e.value); } /** * 刪除“鍵為key”元素 */ final Entry<K,V> removeEntryForKey(Object key) { if (size == 0) { return null; } int hash = (key == null) ? 0 : hash(key);//key==null ,hash==0 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; //本質(zhì)是“刪除單向鏈表中的節(jié)點” 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; } /** * 不做分析 */ final Entry<K,V> removeMapping(Object o) { if (size == 0 || !(o instanceof Map.Entry)) } /** * 清空HashMap */ public void clear() { modCount++; Arrays.fill(table, null);//使用了Arrays.fill方法 size = 0; //設(shè)置HashMap的大小為 0 } /** * 判斷HashMap中是否有對于的value * 有對應(yīng)的value返回 true * 也是分為null了和非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; } /** *包含null參數(shù)的containsValue的特殊情況代碼 */ 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; } /** * 實現(xiàn)了Cloneable,實現(xiàn)clone 方法 */ public Object clone() { HashMap<K,V> result = null; try { 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(); // 調(diào)用putAllForCreate()將全部元素添加到HashMap中 result.putAllForCreate(this); return result; } //Entry是單向鏈表。實現(xiàn)了Map.Entry<K,V>, //即實現(xiàn)getKey(), getValue(), setValue(V value), equals(Object o), hashCode()這些函數(shù) static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next;//下一個節(jié)點 int hash; /** * 創(chuàng)建Entry * 參數(shù)包括"哈希值(h)", "鍵(k)", "值(v)", "下一節(jié)點(n)" */ 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都相等 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; } //實現(xiàn)hashcode public final int hashCode() { return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue()); } public final String toString() { return getKey() + "=" + getValue(); } void recordAccess(HashMap<K,V> m) { } void recordRemoval(HashMap<K,V> m) { } } /** */ 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); } createEntry(hash, key, value, bucketIndex); } /** * */ 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是HashMap迭代器的抽象出來的父類,實現(xiàn)了公共了函數(shù)。 private abstract class HashIterator<E> implements Iterator<E> { Entry<K,V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot Entry<K,V> current; // current entry HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } } public final boolean hasNext() { return next != null; } 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; 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.removeEntryForKey(k); expectedModCount = modCount; } } private final class ValueIterator extends HashIterator<V> { public V next() { return nextEntry().value; } } private final class KeyIterator extends HashIterator<K> { public K next() { return nextEntry().getKey(); } } private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } } // Subclass overrides these to alter behavior of views' iterator() method Iterator<K> newKeyIterator() { return new KeyIterator(); } Iterator<V> newValueIterator() { return new ValueIterator(); } Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); } // Views // 查看HashMap中的元素,返回的是set集合 private transient Set<Map.Entry<K,V>> entrySet = null; /** * 返回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(); } } /** * 繼承AbstractCollection */ 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(); } } /** *返回map的映射的集合 */ 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); } } // 這些方法在序列化HashSets時使用 int capacity() { return table.length; }// 返回“HashMap總的容量” float loadFactor() { return loadFactor; }// 返回“HashMap的加載因子” }

5.總結(jié)

(1):HashMap是通過哈希表來存儲一個key-value的鍵值對,每個key對應(yīng)一個value,允許key和value為null! hash (2):HashMap 的實例有兩個參數(shù)影響其性能:初始容量 和加載因子。容量是哈希表中桶的數(shù)量,初始容量只是哈希表在創(chuàng)建時的容量。HashMap的容量不足的時候,可以自動擴容resize(),但是最大容量為MAXIMUM_CAPACITY==2^30!

(3):put和get都是分為null和非null進行判斷!

(4):resize非常耗時的操作,因此,我們在用HashMap的時,最好能提前預(yù)估下HashMap中元素的個數(shù),這樣有助于提高HashMap的性能。 (5):求hash值和索引值的方法,這兩個方法便是HashMap設(shè)計的最為核心的部分,二者結(jié)合能保證哈希表中的元素盡可能均勻地散列。

引用:

HashMap中則通過h&(length-1)的方法來代替取模,同樣實現(xiàn)了均勻的散列,但效率要高很多,這也是HashMap對Hashtable的一個改進。 接下來,我們分析下為什么哈希表的容量一定要是2的整數(shù)次冪。 首先,length為2的整數(shù)次冪的話,h&(length-1)就相當(dāng)于對length取模,這樣便保證了散列的均勻,同時也提升了效率; 其次,length為2的整數(shù)次冪的話,為偶數(shù),這樣length-1為奇數(shù),奇數(shù)的最后一位是1,這樣便保證了h&(length-1)的最后一位可能為0,也可能為1(這取決于h的值),即與后的結(jié)果可能為偶數(shù),也可能為奇數(shù), 這樣便可以保證散列的均勻性,而如果length為奇數(shù)的話,很明顯length-1為偶數(shù),它的最后一位是0,這樣h&(length-1)的最后一位肯定為0,即只能為偶數(shù),這樣任何hash值都只會被散列到數(shù)組的偶數(shù)下標(biāo)位置上,這便浪費了近一半的空間, 因此,length取2的整數(shù)次冪,是為了使不同hash值發(fā)生碰撞的概率較小,這樣就能使元素在哈希表中均勻地散列。

參考文章: HashMap源碼剖析:http://blog.csdn.net/ns_code/article/details/36034955

附:

JDK8中HashMap的底層實現(xiàn):http://ericchunli.iteye.com/blog/2356721


歡迎訪問我的csdn博客,我們一同成長!

不管做什么,只要堅持下去就會看到不一樣!在路上,不卑不亢!

博客首頁:http://blog.csdn.net/u010648555


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 郑州市| 淮北市| 安化县| 绵阳市| 卫辉市| 大英县| 巴南区| 梅河口市| 定陶县| 丹巴县| 涞水县| 秀山| 青浦区| 石泉县| 嘉荫县| 肇东市| 丰台区| 阜宁县| 麟游县| 麟游县| 凤城市| 卓资县| 湘潭市| 莒南县| 株洲县| 泸溪县| 松江区| 石城县| 合作市| 泰宁县| 扶绥县| 新津县| 大同县| 应用必备| 和硕县| 巴彦县| 湘潭市| 会理县| 双江| 英吉沙县| 长海县|