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 ...
随机推荐
- fiddler(二)、配置抓取https协议
打开fiddler,用火狐或者谷歌浏览器访问https协议的网页,如:https://www.baidu.com/,会报不安全的连接错误 这时就需要我们做一些配置,才能抓取https协议的网页. 首先 ...
- 使用单调队列维护决策三元组实现决策单调性优化DP的一些细节
以[BZOJ2687]交与并为例给出代码. #include <bits/stdc++.h> #define rin(i,a,b) for(register int i=(a);i< ...
- CentOS版本禁用Ctrl+Alt+Del重启功能
1 禁用Ctrl+Alt+Del重启功能(不重启系统的前提条件) 1.1 CentOS 6 ##查看/etc/inittab确认Ctrl+Alt+Del相关配置文件 cat /etc/initta ...
- RabbitMq运行原理浅析
转载:https://blog.csdn.net/Evankaka/article/details/80977027 1.RabbitMq简介 AMQP,即Advanced Message Q ...
- 死磕java多线程
1.线程和进程 1.1线程和进程的区别 进程 它是内存中的一段独立的空间,可以负责当前应用程序的运行.当前这个进程负责调度当前程序中的所有运行细节(操作系统为进程分配一块独立的运行空间): 线程 它是 ...
- LeetCode 79. 单词搜索(Word Search)
题目描述 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被 ...
- python开发环境的搭建,以及pycharm的安装
先到python 官网下载python. 下载好了之后,直接运行exe文件,进行安装(在安装程序运行后的第一个form上,点击next的时候,在next的左侧有一排文字和一个复选框,那个是添加环境变量 ...
- SpringBoot启动加载yml配置文件出现编码格式错误
Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input l ...
- LinkedList,ArrayList,Vector,HashMap,HashSet,HashTable之间的区别与联系
在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...
- EC