1.Map集合概念及特点
1.1 概念
interface Map<K,V> //K:键的类型 V:值的类型
1.2 Map集合的特点
- 键值对映射关系,一个键对应一个值
- 键不能重复,值可以重复元素存取无序
2. Map集合基本功能
方法名 | 说明 |
---|---|
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
3. Map集合的获取功能
方法名 | 说明 |
---|---|
V get(Object key) | 根据键获取值 |
Set<K> keySet() | 获取所有键的集合 |
Collection<V> values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
4. Map集合的遍历
方法一:把Map集合的键集中起来,遍历键的集合,获取到每一个键,再根据键找对应的值。(代码如下)
public class MapDemo(){
public static void main(String[] args){
//创建集合对象
Map<String,String> map=new HashMap<String,String>();
//添加元素
map.put("恭喜","发财");
map.put("事事","如意");
map.put("平安","喜乐");
//获取所有键的集合。用KeySet()方法实现
Set<String> keySet =map.keySet();
//遍历键的集合,获取到每一个键。用增强for循环实现
for(String key:keySet){
//根据键的集合。用get(Object key)方法实现
String value=map.get(key);
System.out.println(key+","+value);
}
}
}
方法二:获取所有键值对对象的集合 (Set<Map.Entry<K,V>> entrySet())得到每一个键值对对象,用增强for循环得到每一个Map.Entry(),根据键值对对象来获取键和值,用getKey()得到键,用getValue()得到值(代码如下)
public class MapDemo01{
public static void main(String[] args){
//创建集合对象
Map<String,String> map=new HashMap<String,String>();
//添加元素
map.put("恭喜","发财");
map.put("事事","如意");
map.put("平安","喜乐");
//获取所有键值对的集合
Set<Map.Entry<String,String>> entrySet =map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for(Map.Entry<String,String> me:entrySet){
//根据键值对对象获取键和值
String key=me.getKey();
String value=me.getValue();
System.out.println(key+","+value);
}
}
}
5. HashMap集合
HashMap集合概念和特点
- HashMap底层是哈希表结构
- 依赖hashCode方法和equals方法保证键的唯一
- 如果要存储的是自定义对象,需要重写hashCode和equals方法
HashMap相关面试题
1.HashMap的特性?
- HashMap存储键值对实现快速存取,允许为null。key值不可以重复,若key值重复则覆盖。
- 非同步,线程不安全。
- 底层是hash表,不保证有序。
2.谈一下HashMap的JDK7和JDK8底层结构是什么?
- JDK7使用的是数组+链表。
- JDK8使用的是数组+链表+红黑树。
3.链表的作用是什么?为什么JDK8引入了红黑树?
- 链表主要是为了解决数组中key发生hash冲突时,将发生碰撞的key存到链表中
- 红黑树主要为了解决链表过长导致查询速度太慢问题,链表查询时间复杂度为O(n)
- 当链表长度大于等于8时,就会转变为红黑树,时间复杂度为O(logn)
- 当链表长度小于等于6时,由红黑树转变为链表,因为链表过短时引入红黑树反而会降低查询效率
4.什么是hash冲突?
当两个不同的值输入,根据同一散列函数计算相同的散列值的现象,我们称之为碰撞(Hash碰撞)。
5.有什么办法能减少hash冲突?
- 使用链地址法(使用散列表)来链接拥有相同hash值的数据,就是我们上文所说的链表。
- 使用两次扰动函数(hash函数)来降低哈希冲突的概率,使数据分布的更加平均
- 引入红黑树进一步降低遍历的时间复杂度,是遍历的更快
6.说一说HashMap什么时候会进行扩容?扩容多大
HashMap有个参数叫负载因子,其实就是一个小数值0.75,例如map的默认大小为16,当填满75%的空间就该扩容了,也就是说存到12个就该进行提前扩容了。
7.谈谈你对红黑树的见解?
- 每个节点非红即黑
- 根节点总是黑色的
- 如果节点是红色的,则它的子节点必须是黑色的(反之则不一定)
- 每个叶子节点都是黑色的空节点
- 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)
8.链表过深问题为什么不用二叉查找树代替,而选择红黑树?为什么不一直使用红黑树?
- 选择红黑树是为了解决二叉查找树的缺陷,二叉查找树在特殊情况下会变成一条线性结构(这就跟原来使用链表结构一样了,造成很深的问题),遍历查找会非常慢。
- 而红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,引入红黑树就是为了查找数据快,解决链表查询深度的问题
- 我们知道红黑树属于平衡二叉树,但是为了保持“平衡”是需要付出代价的,但是该代价所损耗的资源要比遍历线性链表要少
- 所以当长度大于8的时候,会使用红黑树,如果链表长度很短的话,根本不需要引入红黑树,引入反而会慢。
6. TreeMap集合
- TreeMap底层是红黑树结构。红黑树详解
- 依赖于自然排序或者是比较器排序,对键进行排序
- 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象的时候给出比较器排序规则
7.ConcurrentHashMap面试题
1.ConcurrentHashMap1.7和1.8的区别;
- jdk1.7:分段锁Segment来进行实现的,Segment继承了ReentrantLock锁;
- jdk1.8:放弃了Segment臃肿的设计,采用volatile+Node+CAS+Synchronized来保证线程安全;
2.JDK1.7的ConcurrentHashMap的实现原理
- ConcurrentHashMap中采用了分段锁保证了线程安全
- 分段锁称为Segment,它即类似于HashMap的结构,即内部拥有一个Entry数组,
- 数组中的每个元素又是一个链表,同时又是一个ReentrantLock
- 因为Segment继承了ReentrantLock。
- ReentrantLock就是实现多线程锁的关键
- 所谓的分段锁就是将数据分成一段一段的存储,
- 然后给每一段数据配一把锁,
- 当一个线程占用锁访问其中一个段数据的时候,
- 其他段的数据也能被其他线程访问,能够实现真正的并发访问。
3.JDK1.8的ConcurrentHashMap的实现原理
- 抛弃了原有的 Segment 分段锁,
- 采用了volatile+CAS+ synchronized来保证并发安全性
4.HashMap和HashTable的区别
-
默认容量不同,扩容不同
-
线程安全性:HashTable 安全
-
效率不同:HashTable 要慢,因为加锁
-
对于HashMap来说,可以存放null键和null值,而HashTable则不可以。
5.可以使用 CocurrentHashMap 来代替 Hashtable 吗?
- 我们知道 Hashtable 是 synchronized 的,但是 ConcurrentHashMap 同步性能更好,因为它仅仅根据同步级别对 map 的一部分进行上锁
- ConcurrentHashMap 当然可以代替 HashTable,但是 HashTable 提供更强的线程安全性
- 它们都可以用于多线程的环境,但是当 Hashtable 的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。由于 ConcurrentHashMap 引入了分割(segmentation),不论它变得多么大,仅仅需要锁定 Map 的某个部分,其它的线程不需要等到迭代完成才能访问 Map。简而言之,在迭代的过程中,ConcurrentHashMap 仅仅锁定 Map 的某个部分,而 Hashtable 则会锁定整个 Map。
8.总结
Map集合是Java三大集合之一,常在开发中用到,也是面试常考题,希望读者多多阅读,多看源码了解更深层的原理。