HashMap底层原理
来源:互联网 发布:benq显示器怎么样 知乎 编辑:程序博客网 时间:2024/05/20 07:19
首先简单说说HashMap和HashTable的区别:
- 最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合;
- HashMap可以使用null作为key,而Hashtable则不允许null作为key;
- HashMap的初始容量为16,Hashtable初始容量为11;
- HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类;
- 两者计算hash的方法不同,Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模,HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸;
HashMap和Hashtable的底层实现都是数组+链表结构实现。
接下来简要分析HashMap和HashTable的底层实现原理:
HashMap的put方法
首先看接口的put方法定义
/** * Associates the specified value with the specified key in this map * (optional operation). If the map previously contained a mapping for * the key, the old value is replaced by the specified value. (A map * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only * if {@link #containsKey(Object) m.containsKey(k)} would return * <tt>true</tt>.) * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>, * if the implementation supports <tt>null</tt> values.) * @throws UnsupportedOperationException if the <tt>put</tt> operation * is not supported by this map * @throws ClassCastException if the class of the specified key or value * prevents it from being stored in this map * @throws NullPointerException if the specified key or value is null * and this map does not permit null keys or values * @throws IllegalArgumentException if some property of the specified key * or value prevents it from being stored in this map */ V put(K key, V value);
HashMap会对null值key进行特殊处理,总是放到table[0]位置
put过程是先计算hash然后通过hash与table.length取摸计算index值,然后将key放到table[index]位置,当table[index]已存在其它元素时,会在table[index]位置形成一个链表,将新添加的元素放在table[index],原来的元素通过Entry的next进行链接,这样以链表形式解决hash冲突问题,当元素数量达到临界值(capactiy*factor)时,则进行扩容,是table数组长度变为table.length*2
再看HashMapput()方法的源码
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) 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; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
再看HashMap的get()方法
get方法
同样当key为null时会进行特殊处理,在table[0]的链表上查找key为null的元素
get的过程是先计算hash然后通过hash与table.length取摸计算index值,然后遍历table[index]上的链表,直到找到key,然后返回
/** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * <p>More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code (key==null ? k==null : * key.equals(k))}, then this method returns {@code v}; otherwise * it returns {@code null}. (There can be at most one such mapping.) * * <p>A return value of {@code null} does not <i>necessarily</i> * indicate that the map contains no mapping for the key; it's also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey containsKey} operation may be used to * distinguish these two cases. * * @see #put(Object, Object) */ public V get(Object key) { if (key == null) return getForNullKey(); Entry<K,V> entry = getEntry(key); return null == entry ? null : entry.getValue(); }
最后看remove()方法
remove方法和put get类似,计算hash,计算index,然后遍历查找,将找到的元素从table[index]链表移除
/** * Removes the mapping for the specified key from this map if present. * * @param key key whose mapping is to be removed from the map * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V remove(Object key) { Entry<K,V> e = removeEntryForKey(key); return (e == null ? null : e.value); }
0 0
- Java Hashmap底层原理
- HashMap底层原理
- hashMap底层原理
- HashMap底层实现原理
- HashMap底层原理
- HashMap底层实现原理
- HashMap底层原理
- HashMap的底层原理
- HashMap底层实现原理
- HashMap的底层原理
- HashMap底层原理
- HashMap底层实现原理
- HashMap底层存储原理
- HashMap 底层原理
- HashMap底层原理
- JAVA HashMap底层实现原理
- hashMap的底层实现原理
- java --HashMap底层原理解读
- RDD详解
- C++容器类的介绍和例子源代码
- Activity大全
- 新手看Mockplus
- Android Studio的插件
- HashMap底层原理
- 225. Implement Stack using Queues
- 动规-计数DP
- lambda类型作为模板Concept
- Could not set property 'xxxx' of 'class 'xxxxxxx' with value 'xxxxxx'
- 1IntelliSense: #error 指令: Please use the /MD switch for _AFXDLL buildsc:\program files\microsoft
- 动规-矩阵快速幂
- 匿名对象不同的jdk5新特性
- 加速加速boo!