美文网首页
HashMap的数据结构是什么?如何实现的。和HashTable

HashMap的数据结构是什么?如何实现的。和HashTable

作者: 小七_8d72 | 来源:发表于2018-03-08 09:45 被阅读0次

    HashMap和HashTable的区别一种比较简单的回答是:

    (1)HashMap是非线程安全的,HashTable是线程安全的。

    (2)HashMap的键和值都允许有null存在,而HashTable则都不行。

    (3)因为线程安全、哈希效率的问题,HashMap效率比HashTable的要高。

    JAVA的数据结构存储:

    1、数组:查询快,增删慢;连续空间寻址快。

    2、链表:增删快,查询慢;空间不连续,增删只需修改指针。

    Hash表结构:

    从下图中,我们可以发现哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点,通过功能类似于hash(key.hashCode())%len的操作,获得要添加的元素所要存放的的数组位置。

    HashMap的哈希算法实际操作是通过位运算,比取模运算效率更高,同样能达到使其分布均匀的目的,后面会介绍。

    键值对所存放的数据结构其实是HashMap中定义的一个Entity内部类,数组来实现的,属性有key、value和指向下一个Entity的next。

    HashMap的实现重点需要注意的在两个方面,一个是链表结构,一个是table的resize()扩容;

    HashMap和HashTable的对比:

    HashTable和HashMap采用相同的存储机制,二者的实现基本一致,不同的是:

    (1)HashMap是非线程安全的,HashTable是线程安全的,内部的方法基本都经过synchronized修饰。

    (2)因为同步、哈希性能等原因,性能肯定是HashMap更佳,因此HashTable已被淘汰。

    (3) HashMap允许有null值的存在,而在HashTable中put进的键值只要有一个null,直接抛出NullPointerException。

    (4)HashMap默认初始化数组的大小为16,HashTable为11。前者扩容时乘2,使用位运算取得哈希,效率高于取模。而后者为乘2加1,都是素数和奇数,这样取模哈希结果更均匀。

    言归正传,看下两种集合的hash算法。看源码也不难理解。

    //HashMap的散列函数,这里传入参数为键值对的key  

    static final int hash(Object key) {  

    int h;  

    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);  

    }   

    //返回hash值的索引,h & (length-1)操作等价于 hash % length操作, 但&操作性能更优  

    static int indexFor(int h, int length) {  

    // length must be a non-zero power of 2  

    return h & (length-1);  

    }  

    //HashTable的散列函数直接在put方法里实现了  

    int hash = key.hashCode();  

    int index = (hash & 0x7FFFFFFF) % tab.length;

    ConcurrentHashMap原理:

    ConcurrentHashMap引入了分割(Segment),上面代码中的最后一行其实就可以理解为把一个大的Map拆分成N个小的HashTable,在put方法中,会根据hash(paramK.hashCode())来决定具体存放进哪个Segment,如果查看Segment的put操作,我们会发现内部使用的同步机制是基于lock操作的,这样就可以对Map的一部分(Segment)进行上锁,这样影响的只是将要放入同一个Segment的元素的put操作,保证同步的时候,锁住的不是整个Map(HashTable就是这么做的),相对于HashTable提高了多线程环境下的性能,因此HashTable已经被淘汰了。

    HashMap和ConCurrentHashMap的对比

    最后对这俩兄弟做个区别总结吧:

    (1)经过4.2的分析,我们知道ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的syn关键字锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。

    (2)HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。

    所以 HashMap 与 ConcurrentHashMap 区别为 CHM部分方法具备原子性,CHM原子性 基于CAS实现,CAS是乐观锁实现同步的一种方式

    使用concurrentHashMap随便操作是原子性,但是放一起可能违反happen-before规则,chm是弱一致,要想强一致必须使用全局锁

    建议使用以下代码

        Map map = Collections.synchronizedMap(newHashMap());

        String getString(String name) { 

            synchronized(map){//可保证该同步块内的所有代码对map是一个原子操作。

                String x = map.get(name); 

                if(x == null) { 

                    x = newString(); 

                    map.put(name, x); 

                } 

                returnx;

            } 

        } 

    相关文章

      网友评论

          本文标题:HashMap的数据结构是什么?如何实现的。和HashTable

          本文链接:https://www.haomeiwen.com/subject/vkejfftx.html