Map:双列结构,用来存储Key-Value键值对
1常用的实现类结构
- HashMap: Map的主要实现类,线程不安全,效率高,可以存储Null的Key和Value。
- LinkedHashMap: 在遍历Map结构时,可以按照添加的顺序实现遍历。原因:在HashMap底层结构的基础上添加指针,指向前一个和后一个元素。对于频繁的遍历操作,执行效率高于HashMap。(是HashMap的子类)
- TreeMap: 保证照添加的Key-Value对进行排序,实现排序遍历。此时考虑Key的自然排序或定制排序,底层使用红黑树。
- HashTable:较为古老的实现类,线程安全,效率低,不能存储Null的key和value。
- Properties:用来处理配置文件,HashTable的子类,key和value都是字符串。
HashMap的底层: 在JDK7之前是数组+链表,在JDK8之后是数组+链表+红黑树。
面试题:
1.HashMap的底层实现原理?
2.HashMap和Hashtable的异同?
3.CurrentHashMap与Hashtable的异同?
2存储结构的理解
- Map中的key是无序的,不可重复的,采用set进行存储。(key所在的类要重写equals()和hashcode()方法)
- Map中的value是无序的,可重复的,采用Collection进行存储。(Value所在的类需要重写equals()方法)
- Map中的entry:无序的,不可重复的,采用set进行存储。
图示:
3常用方法
- 增:put(Object key,Object Value)
- 删: remolve(Object key,Object Value)
- 改: put(Object key,Object Value)
- 查: get(Object key,Object Value)
- 长度: size()
- 遍历: keySet() / values() / entrySet()
4内存结构说明(难点)
4.1 HashMap在JDK7的底层实现原理
- 执行的HashMap hashmap = new HaspMap()后,底层会创建长度为16的Entry[] table数组
- …执行多次put操作…
- 进行第n次put(key1,value1)时,通过key1计算出hashcode值,通过映射后得到在数组上的存储位置
- 如果此时存储位置为空,则添加成功。(情况1)
- 如果此存储位置非空,意味着以链表的形式存储着一个或多个元素,此时比较key1和已经存在的一个或多个元素的哈希值。
------> 如果key1的哈希值与已经存在的一个或者多个元素的哈希值都不相同,添加成功(情况2)
------> 如果key1的哈希值与已经存在的一个或者多个元素的哈希值相同,调用key1.equals(key2),如果返回false,则key1-value1添加成功,如果返回true,则使用value1替换value2(情况3)
- 在添加的过程中,可能会涉及到扩容问题,当超出临界值,且要存放的位置非空时扩容。扩容方式:容量扩容为2倍,将原数据复制过来。
4.2 HashMap在JDK8和JDK7中的异同
- new HashMap():底层没创建一个长度为16的数组,只有进行put操作时才创建
- JDK 8底层是Node数组而不是Entry
- JDK7底层:数组+链表 JDK8底层:数组+链表+红黑树
- 在形成链表时,jdk7是从旧元素指向新元素,jdk8是新元素指向旧元素
- 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8,且当前数组长度 > 64时,此时此索引位置上的数据改为红黑树存储 (所以map结构上可能既有链表又有红黑树)
4.3HashMap底层属性说明
DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树
UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。(当桶中Node的
数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行
resize扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4
倍。)
table:存储元素的数组,总是2的n次幂
entrySet:存储具体元素的集
size:HashMap中存储的键值对的数量
modCount:HashMap扩容和结构改变的次数。
threshold:扩容的临界值,=容量*填充因子
loadFactor:填充因子
4.4LinkedHashMap的底层实现原理(了解)
底层结构和HashMap结构一致,区别就是LinkedHashMap自己定义了一个Entry结构来替换HashMap中的Node。
5 TreeMap的使用
- 向TreeMap中添加Key-Value,要求Key必须是同一个类创建的对象
- 因为要照Key进行排序:自然排序、定制排序