HashMap

HashMap

HashMap基于哈希表的 Map 接口的实现。允许使用 null 值和 null 键。不保证映射的顺序,特别是它不保证该顺序恒久不变。HashMap不是线程安全的,可以通过Collections类的静态方法synchronizedMap获得线程安全的HashMap。

HashMap的底层主要是基于数组和链表来实现的。HashMap中主要是通过key的hashCode来计算hash值的,只要hashCode相同,计算出来的hash值就一样。如果存储的对象对多了,就有可能不同的对象所算出来的hash值是相同的,这就出现了所谓的hash冲突。解决hash冲突的方法有很多,HashMap底层是通过链表来解决hash冲突的。

图中,紫色部分即代表哈希表,也称为哈希数组,数组的每个元素都是一个单链表的头节点,链表是用来解决冲突的,如果不同的key映射到了数组的同一位置处,就将其放入单链表中。

HashMap其实就是一个Entry数组,Entry对象中包含了键和值,其中next也是一个Entry对象,它就是用来处理hash冲突的,形成一个链表。

/** Entry是单向链表。    
     * 它是 “HashMap链式存储法”对应的链表。    
     *它实现了Map.Entry 接口,即实现getKey(), getValue(), setValue(V value), equals(Object o), hashCode()这些函数  
    **/  
 static class Entry<K,V> implements Map.Entry<K,V> {  
        final K key;    
        V value;    
        // 指向下一个节点    
        Entry<K,V> next;    
        final int hash; 
        
        // 构造函数。    
        // 输入参数包括"哈希值(h)", "键(k)", "值(v)", "下一节点(n)"    
        Entry(int h, K k, V v, Entry<K,V> n) {    
            value = v;    
            next = n;    
            key = k;    
            hash = h;    
        } 

        //......
}

HashMap类的关键属性

1 transient Entry[] table;//存储元素的实体数组    默认初始长度为 16
2  
3 transient int size;//存放元素的个数
4  
5 int threshold; //临界值   当实际大小超过临界值时,会进行扩容threshold = 加载因子*容量
6 
7  final float loadFactor; //加载因子  默认0.75
8  
9 transient int modCount;//被修改的次数

注意:

1、HashMap中通过hash&(length-1)的方法来代替取模(Hashtable中)来实现哈希值对应数组下标的映射。
2、哈希表的容量一定要是2的整数次幂,保证散列的均匀。
3、当哈希表的size>threshold时,则调用Resize方法,此方法新建一个2*size的数组,并将旧数组中的数据复制到新数组中,所以效率很低。


参考原文:
http://www.cnblogs.com/ITtangtang/p/3948406.html#a9

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容