一、Map接口
双列集合(key - value)- 映射关系
1.概述
Map是一种以 键值对(key-value)进行存储的集合,Map集中的每一个元素都包含一个
键(key) 对象 和 一个值(value)对象.
2.特点
①.key和value都可以使用泛型,也就意味着是可以存储任意的引用数据类型.
②.key值不允许重复,value可以重复
③.因为key是唯一的,可以通过key,找到对应的value值.
④.Map是最大的接口,上面没有接口,也就意味着没有实现Iterable接口.
不能使用迭代器,所以Map集合是不可迭代的.
3.Map的分支结构
Map(I)
|- HashMap© - 散列结构
|- LinkedHashMap© - 线性结构
|- SortedMap(I)
|- TreeMap© - 二叉树
|- HashTable©
|- properties©
|- ConCurrentHashMap© -> jdk1.7/jdk1.8
4.HashMap类
1)底层实现:
jdk1.7: 数组 + 链表(Entry)
插入方式: 头插法
理解: 新插入的值会取代原有的值,原有的值就会顺推到链表中
新插入的值被查到的可能性就更大一些,提升查询效率.
jdk1.8: 数组 + 链表 | 红黑树(Node)
插入方式: 尾插法
理解: 在扩容的时候会保持链表原本的顺序,就不会出现链表成环
2)存储过程:
a.计算key的hashCode值,确定在内存中存储的位置
b.判断该位置上是否有元素
c.如果有元素,则调用key的equals()进行判断元素是否一致
d.如果一致,则会进行覆盖
e.如果不一致,则遍历下一个节点,然后继续使用equals()判断,直到链表尾部,
都不一致,则添加到链表尾部.
3)扩容大小
a.如果太小,会造成链表过长,效率低
b.如果太大,空间浪费,时间浪费
4)扩容条件:
a.加载因子: 默认0.75(空间存储到75%后扩容)
5)Map的迭代方式
①.遍历key,获取所对应的Set类型
Set keySet();
②.遍历value,获取所对应的Collection类型
Collection values()
③.获取键值对entry, 返回的是set类型集合
Set<Map.Entry<泛型,泛型>> entrySet
5.TreeMap类
1)底层数据结构: 二叉树(红黑树)
2)作用: 根据java提供的自然排序或者比较器排序方式,堆键进行排序.
3)注意: 如果键值对存储自定义对象,需要实现Comparable接口,
或者在创建TreeMap对象时使用匿名内部类方式实现Comparator接口.
6.HashTable类
1)底层数据结构: 哈希表
2**)特点**:
①.不允许存在null值,存在的话会抛出空指针异常.
②.带有锁机制,是现线程安全的,运行速度慢.
3)子类: Properties
作用: 结合IO流使用,实现数据的持久存储(配置文件)
7.ConcurrentHashMap类
1)是一个JDK1.5以后出现的一个支持高并发的集合类.
2)数据结构:
jdk1.7: 数组 + 链表
①.锁分段技术: Segment数组 + HashEntry
jdk1.8: 数组 + 链表 | 红黑树 (TreeBin)
①.CAS + synchronized
②.volatile修饰变量,保证了可见性.
3)存储过程:
a.根据key的hashCode,计算地址值.
b.判断是否要进行初始化操作. -> 初始化时涉及自旋操作.
c.当前key位置上如果是空,则进行初始化操作
(使用CAS尝试写入数据,如果写入不成功则进行自旋操作,直到成功为止)
(达到xxx 这进行扩容操作)
d.如果都不满足上面的情况,则使用synchronized 写入数据.
(判断当前数据大于xxx 则要转换成红黑树)
8.面试题[重要!!!]
- HashMap的原理? *****
- ConcurrentHashMap的原理?
- HashMap、ConcurrentHashMap、HashTable的区别?
- volatile关键词
- CAS? ABA问题? 怎么解决ABA问题?
CAS: 在读取不进行加锁,在准备写回数据,会进行比较数据,比较原数据是否进行了修改。
如果没有被其他线程修改则直接写会。
如果被修改了,则重新执行读取操作。