1、Hashmap
线程不安全 实现方式:数组+链表或红黑树 初始容量 16,当达到loadFactor(默认为0.75)后进行扩容,每次扩容容量 oldsize*2+1 index值计算 在Object中的hashcode基础上再运算 index = hash & (tab.length – 1) 哈希冲突:hashcode根据key计算得到int值,如果两个或多个值落在同一个位置上时则会产生冲突,再使用所有的Key值使用equals进行比较;同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾; 当你的key为null时,会调用putForNullKey,HashMap允许key为null,这样的对像是放在table[0]中。 加载因子:为了降低哈希冲突的概率,默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。因此,如果预估容量是100,即需要设定100/0.75=134的数组大小。(如果希望加快Key查找的时间,还可以进一步降低加载因子,加大初始大小,以降低哈希冲突的概率。) 判断是否有key存在 map.containsKey(“key”); 使用get方法时,不管是key不存在或者value为空的情况下都会返回null;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4 ;
static final float DEFAULT_LOAD_FACTOR = 0.75f ;
2、ConcurrentHashMap(HashTable )
2.1 hashtable
线程安全,其中大致实现原理与hashmap一致,只是在针对整张hash表的synchronized 不允许空的key或者value出现
2.2 ConcurrentHashMap
线程安全,不同于hashtable的一次将整张Hash表锁住的方式,默认效率提升了16倍,在其中多了Segment的概念(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。) ConcurrentHashMap采用锁分段技术,将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁。 ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。