Java基础面试必问,必问,必问
三个最关键的区别就是线程安全的区别
- 四者均实现了Map接口,存储的内容是基于key-value的键值对映射,一个映射不能有重复的键,一个键最多只能映射一个值。
从元素特性讲
- HashTable的key、value都不能为null;
- HashMap中的key、value可以为null,很显然只能有一个key为null的键值对,但是允许有多个值为null的键值对;由于它的键可以是为空的,所以,所以我们不能用get(key)判断是否有这个键,而应该用containsKey()这个方法来判断是否有这个键;
- TreeMap中当未实现 Comparator 接口时,key 不可以为null;当实现 Comparator 接口时,若未对null情况进行判断,则key不可以为null,反之亦然;
顺序特性
- HashTable、HashMap具有无序特性。
- TreeMap是利用红黑树来实现的(树中的每个节点的值,都会大于或等于它的左子树种的所有节点的值,并且小于或等于它的右子树中的所有节点的值),实现了SortMap接口,能够对保存的记录根据键进行排序。所以一般需要排序的情况下是选择TreeMap来进行,默认为升序排序方式(深度优先搜索),可自定义实现Comparator接口实现排序方式。
初始化与增长方式
- 初始化时:
- HashTable在不指定容量的情况下的默认容量为11,且不要求底层数组的容量一定要为2的整数次幂;
- HashMap默认容量为16,且要求容量一定为2的整数次幂。
- 扩容时:
- Hashtable将容量变为原来的2倍加1;HashMap扩容将容量变为原来的2倍。
线程安全
- HashTable其方法函数都是同步的(采用synchronized修饰),不会出现两个线程同时对数据进行操作的情况,因此保证了线程安全性。也正因为如此,在多线程运行环境下效率表现非常低下。因为当一个线程访问HashTable的同步方法时,其他线程也访问同步方法就会进入阻塞状态。比如当一个线程在添加数据时候,另外一个线程即使执行获取其他数据的操作也必须被阻塞,大大降低了程序的运行效率,在新版本中已被废弃,不推荐使用。
- HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。
- HashMap如果需要同步(1)可以用 Collections的synchronizedMap方法;(2)使用ConcurrentHashMap类,相较于HashTable锁住的是对象整体, ConcurrentHashMap基于lock实现锁分段技术。首先将Map存放的数据分成一段一段的存储方式,然后给每一段数据分配一把锁,当一个线程占用锁访问其中一个段的数据时,其他段的数据也能被其他线程访问。ConcurrentHashMap不仅保证了多线程运行环境下的数据访问安全性,而且性能上有长足的提升。
CurrentHashMap和HashMap
- 上面已经知道HashMap是线程不安全的了,后来在jdk1.5的时候就出来了CurrentHashMap来弥补HashMap的线程不安全的特性;CurrentHashMap,是将HashMap分成了很多个片(一般默认是16片),引入了分段锁的概念,然后对每一片加锁,具体可以理解成一把大的Map分解成N个小的HashTable,根据key.hashCode()来决定放到哪一个片上;
效率的比较:
- 由于安全机制的原因,HashMap的效率比HashTable,CurrentHashMap的效率高;但是由于CurrentHashMap加锁的高效性,HashTable是整个加锁,他的效率比HashTable高; 总的来说 HashMap>CurrentHashMap>HashTable;
HashMap的存储原理
面试有可能会被问到,我都被问到好几次了
- 还挺复杂的啊,
HashMap数据结构的优点
- 适合海量数据,o(1)的随机访问速度,不是可遍历;
网友评论