HashMap、HashTable、ConcurrentHashMap、TreeMap、LinkedHashMap、WeakHashMap区别
1. HashMap
标准链地址法实现(下图)。数组方式存储key/value
,线程非安全,允许null
作为key
和value
,key
不可以重复,value
允许重复,不保证元素迭代顺序是按照插入时的顺序,key
的hash
值是先计算key
的hashcode
值,然后再进行计算,每次容量扩容会重新计算所以key
的hash
值,会消耗资源,要求key
必须重写equals
和hashcode
方法。默认初始容量16
,加载因子0.75
,扩容为旧容量乘2
,查找元素快,如果key
一样则比较value
,如果value
不一样,则按照链表结构存储value
。如果需要同步,可以用 Collections
的synchronizedMap
方法(Map m = Collections.synchronizedMap(new HashMap(…));
)。使HashMap
具有同步的能力,或者使用ConcurrentHashMap
。
JDK 1.8之后,加入了static final int TREEIFY_THRESHOLD = 8;
,当同一桶内元素个数超过8个,就会将链表结构进行树化。
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
2. HashTable
线程安全,不允许有null
的键和值,线程安全的,它在所有涉及到多线程操作的都加上了synchronized
关键字来锁住整个table
,这就意味着所有的线程都在竞争一把锁,在多线程的环境下,它是安全的,但是无疑是效率低下的。
3. ConcurrentHashMap
HashTable
有很多的优化空间,锁住整个table
这么粗暴的方法可以变相的柔和点,比如在多线程的环境下,对不同的数据集进行操作时其实根本就不需要去竞争一个锁,因为他们不同hash
值,不会因为rehash
造成线程不安全,所以互不影响,这就是锁分离技术,将锁的粒度降低,利用多个锁来控制多个小的table
,这就是ConcurrentHashMap
JDK1.7版本的核心思想。
JDK1.7的实现
在JDK1.7版本中,ConcurrentHashMap
的数据结构是由一个Segment
数组和多个HashEntry
组成,如下图所示:
Segment
数组的意义就是将一个大的table
分割成多个小的table
来进行加锁,也就是上面的提到的锁分离技术,而每一个Segment
元素存储的是HashEntry
数组+链表,这个和HashMap
的数据存储结构一样
JDK1.8的实现
JDK1.8的实现已经摒弃了Segment
的概念,而是直接用Node
数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized
和CAS
来操作,整个看起来就像是优化过且线程安全的HashMap
,虽然在JDK1.8中还能看到Segment
的数据结构,但是已经简化了属性,只是为了兼容旧版本。
4. TreeMap
TreeMap
实现SortMap
接口,基于红黑二叉树的NavigableMap
的实现,线程非安全,不允许null
,key
不可以重复,value
允许重复,存入TreeMap
的元素应当实现Comparable
接口或者实现Comparator
接口,会按照排序后的顺序迭代元素,两个相比较的key
不得抛出classCastException
。主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出
5. LinkedHashMap
LinkedHashMap
是HashMap
的一个子类,保存了记录的插入顺序,在用Iterator
遍历LinkedHashMap
时,先得到的记录肯定是先插入的。也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap
慢,不过有种情况例外,当HashMap
容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap
慢,因为LinkedHashMap
的遍历速度只和实际数据有关,和容量无关,而HashMap
的遍历速度和他的容量有关。
6. WeakHashMap
WeakHashMap
,从名字可以看出它是某种 Map
,允许null
作为key
和value
(Both null values and the null key are supported.),非线程安全(this class is not synchronized)。它的特殊之处在于 WeakHashMap
里的entry
可能会被GC
自动删除,即使程序员没有调用remove()
或者clear()
方法。
更直观的说,当使用 WeakHashMap
时,即使没有显示的添加或删除任何元素,也可能发生如下情况:
- 调用两次
size()
方法返回不同的值;- 两次调用
isEmpty()
方法,第一次返回false
,第二次返回true
;- 两次调用
containsKey()
方法,第一次返回true
,第二次返回false
,尽管两次使用的是同一个key
;- 两次调用
get()
方法,第一次返回一个value
,第二次返回null
,尽管两次使用的是同一个对象。
WeekHashMap
的这个特点特别适用于需要缓存的场景。在缓存场景下,由于内存是有限的,不能缓存所有对象;对象缓存命中可以提高系统效率,但缓存MISS也不会造成错误,因为可以通过计算重新得到。
要明白WeekHashMap
的工作原理,还需要引入一个概念:弱引用(WeakReference)。Java中内存是通过GC自动管理的,GC会在程序运行过程中自动判断哪些对象是可以被回收的,并在合适的时机进行内存释放。GC判断某个对象是否可被回收的依据是,是否有有效的引用指向该对象。如果没有有效引用指向该对象(基本意味着不存在访问该对象的方式),那么该对象就是可回收的。这里的“有效引用”并不包括弱引用。也就是说,虽然弱引用可以用来访问对象,但进行垃圾回收时弱引用并不会被考虑在内,仅有弱引用指向的对象仍然会被GC回收。
WeakHashMap
内部是通过弱引用来管理entry
的,弱引用的特性对应到WeakHashMap
上意味:将一对key, value
放入到WeakHashMap
里并不能避免该key
值被GC
回收,除非在WeakHashMap
之外还有对该key
的强引用。
HashMap、HashTable、ConcurrentHashMap、TreeMap、LinkedHashMap、WeakHashMap区别的更多相关文章
- Java HashMap、HashTable、TreeMap、WeakHashMap区别
1.HashMap不是线程安全,而HashTable是线程安全
- [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.
注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...
- 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.
注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhange ...
- HashMap,HashTable,concurrentHashMap,LinkedHashMap 区别
HashMap 不是线程安全的 HashTable,concurrentHashMap 是线程安全 HashTable 底层是所有方法都加有锁(synchronized) 所以操作起来效率会低 con ...
- HashMap 、HashTable、TreeMap、WeakHashMap的区别是什么
Java为数据结构中的映射定义了一个接口java.util.Map,它有4个实现类:HashTable.HashMap.TreeMap.WeakHashMap. HashMap和HashTable的区 ...
- Java集合——HashMap,HashTable,ConcurrentHashMap区别
Map:“键值”对映射的抽象接口.该映射不包括重复的键,一个键对应一个值. SortedMap:有序的键值对接口,继承Map接口. NavigableMap:继承SortedMap,具有了针对给定搜索 ...
- HashSet、HashMap、Hashtable、TreeMap循环、区别
HashSet 循环 //可以为null HashSet<Object> hashSet =new HashSet<Object>(); hashSet.add(1); has ...
- hashmap,hashTable concurrentHashMap 是否为线程安全,区别,如何实现的
线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多 ...
- Java集合 之Map(HashMap、Hashtable 、TreeMap、WeakHashMap )理解(new)
HashMap 说明: 在详细介绍HashMap的代码之前,我们需要了解:HashMap就是一个散列表,它是通过“拉链法”解决哈希冲突的.还需要再补充说明的一点是影响HashMap性能的有两个参数:初 ...
- Hashtable,HashMap和ConcurrentHashMap的原理及区别
一.原理 Hashtable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashM ...
随机推荐
- Java并发编程的艺术笔记(九)——FutureTask详解
FutureTask是一种可以取消的异步的计算任务.它的计算是通过Callable实现的,多用于耗时的计算. 一.FutureTask的三种状态 二.get()和cancel()执行示意 三.使用 一 ...
- 191022Django模板
一.变量和句点符深度查找 字符串变量引用 def show_time(request): now_time = datetime.datetime.now() return render(reques ...
- Python学习笔记:第一次接触
用的是windows的IDLE(python 3) 对象的认识:先创建一个list对象(用方括号) a = ['xieziyang','chenmanru'] a 对list中对象的引用 a[0] # ...
- ansible 剧本进阶 角色
主要内容: playbook(剧本) roles 一.查看收集到的信息 ansible cache -m setup setup (需要了解的参数) ansible_all_ipv4_addresse ...
- centos7 搭建测试环境
1. 下载JDK8 地址:https://download.oracle.com/otn/java/jdk/8u221-b11/230deb18db3e4014bb8e3e8324f81b43/jdk ...
- C# 利用AForge.NET开源类库实现 图像素描效果
引入DLL: using AForge.Imaging; using AForge.Imaging.Filters; //using AForge.Video.DirectShow;可以使用摄像头图像 ...
- Cross-Multimedia dataset
Wikipedia: http://www.svcl.ucsd.edu/projects/crossmodal/ PKU Xmedia: https://github.com/yeqinglee/mv ...
- Tensorflow所遇坑
TensorFlow问题: 1.FLAGS._parse_flags()报错AttributeError:_parse_flags 解决: 因为TensorFlow的版本问题了,TensorFlow版 ...
- 使用conda安装命令时一直出现问题,因为从2019年4月添加的国内镜像都不能用了
安装过程中出现以下问题:(历尽千辛万苦,终于才查到原来是清华源,腾讯源都不能用了)The remote server could not find the noarch directory for t ...
- jenkins与docker(DevOps二)
Jenkins官网 https://jenkins.io/download/ centos 7安装Docker https://www.cnblogs.com/stulzq/p/7743073.htm ...