hashmap hashtable ConcurrentHashMap的区别
程序员文章站
2022-03-03 08:24:23
...
hashcode与equals:
1、HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的
2、如果两个对象equals相等,那么这两个对象的HashCode一定也相同
3、如果对象的equals方法被重写,那么对象的HashCode方法也尽量重写
4、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置
HashTable
- 底层数组+链表实现,无论key还是value都不能为null,线程安全
- 初始size为11,扩容:newsize = oldsize*2+1
- 计算index的方法 即hash函数:index = (hash & 0x7FFFFFFF) % tab.length
HashMap
- 底层数组+链表实现,可以存储null键和null值,线程不安全
- 初始size为16,扩容:newsize = oldsize*2,size一定为2的n次幂
- 扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入
- 插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)
- 当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀
- 计算index方法:index = hash & (tab.length – 1)
-
ConcurrentHashMap
- 底层采用分段的数组+链表实现,线程安全
- 通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。)
- 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容
map内部有一个Entry类 所有的键值对关系会被封装成一个Entry对象 可以进行获取遍历
for (Map.Entry<String,Integer> entry:map.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
将所有的键值对关系放在set集合内 进行遍历
推荐阅读
-
Java自学-集合框架 HashMap和Hashtable的区别
-
对比Hashtable,HashMap,TreeMap,谈谈对HashMap的理解
-
HashTable与ConcurrentHashMap的区别
-
HashMap在jdk1.7和1.8中的区别
-
HashMap在jdk1.7和1.8中的区别
-
ConcurrentHashMap在jdk1.8和1.7中的区别
-
HashMap和ConcurrentHashMap对null的不同处理
-
HashMap和ConcurrentHashMap对null的不同处理
-
HashMap与Hashtable的区别 面试多线程框架
-
HashMap、HashTable、LinkedHashMap和TreeMap用法和区别