HashMap与Hashtable的区别

时间:2020-03-26
本文章向大家介绍HashMap与Hashtable的区别,主要包括HashMap与Hashtable的区别使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Hashtable:

1)键不可重复,值可以重复,底层哈希表,线程安全的。key和value都不允许为null。

HashMap:

实现:HashMap<K,V> extends AbstractMap<K,V>

键不可重复,值可以重复,线程不安全。允许key和value为null。

构造函数:HashMap():初始容量16,加载因子为0.75。

     HashMap(int initialCapctity):初始容量自定义,加载因子0.75。

     HashMap(int initialCapctity, float loadFactor):初始容量和加载因子都可以自定义。

加载因子:加载因子的系数小于等于1,意指  即当 元素个数 超过 容量长度*加载因子的系数 时,进行扩容。默认为0.75。即表示列表中元素的填满程度,是冲突机会与空间利用率的一种平衡。

数据结构:数组实现,每个位置用链表实现,即数组+链表,当链表长度超过9时转化成红黑树。

public HashMap(int initialCapacity, float loadFactor) {
        //初始容量不能<0
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: "
                    + initialCapacity);
        //初始容量不能 > 最大容量值,HashMap的最大容量值为2^30
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        //负载因子不能 < 0
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: "
                    + loadFactor);

        // 计算出大于 initialCapacity 的最小的 2 的 n 次方值。
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;
        
        this.loadFactor = loadFactor;
        //设置HashMap的容量极限,当HashMap的容量达到该极限时就会进行扩容操作
        threshold = (int) (capacity * loadFactor);
        //初始化table数组
        table = new Entry[capacity];
        init();
    }

看上图源码,每新建一个HashMap时都会初始化一个数组table,table数组中元素为Entry节点。

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        final int hash;

        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }
        .......
    }

CurrentHashMap:

1)底层采用分段的数组+链表实现,线程安全,高效的HashMap实现。

2)通过把整个map分成N个segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于hashentry的value变量是volatile的,能保证读到的最新值)。

3)CurrentHashMap允许多个改操作并发进行,其关键在于使用锁分离技术。

4)有些方法需要跨段,比如size()和containsValue().

5)扩容:段内扩容(段内元素超过该段对应的Entry数组长度的75%触发扩容,不会对整个map扩容),插入前检测不需要扩容,有效避免无效扩容。

CAS无锁算法

原文地址:https://www.cnblogs.com/hjdk05/p/11815515.html