Map(接口):存储k-v键值对双列数据。
主要实现类:
HashMap:Map的主要实现类。线程不安全,效率高,可以存储null类型的key和value。
LinkedHashMap:HashMap的实现类。保证在遍历map时,可以按照添加元素的顺序进行遍历。
原因:在HashMap底层的基础上,添加了指针,一个指向前一个元素,一个指向后一个元素。对于频繁遍历的操作,效率高于HashMap。
TreeMap:按照添加的key-value进行排序,实现排序遍历。可以使用自然排序或则定制排序。底层使用的是红黑树。
Hashtable:Map的古老实现类。线t程安全的,但是效率t低。不可以存储null类型的key和value。
Properties:Hashtable的实现类。常用来处理配置文件,key和value都是String类型。
HashMap的底层:
jdk 7及以前是数组+链表。
jdk 8 是数组+链表+红黑树。
Map中的结构:
key:无序、不可重复的,使用Set存储所有的key。key所在的类要重写hashCode()和equals()方法。
value:无序、可重复的,使用Collection存储所有的value。value所在的类要重写equals()方法。
key-value组成一个Entry对象。entry是无序的,不可重复的,使用Set存储所有的entry。
HashMap底层实现原理(jdk7):
HashMap map = new HashMap();
实例化HashMap的同时,底层创建一个长度为16的数组Entry[] table。
map.put(key,value);
首先调用key所在类的hashCode()计算key的哈希值,此哈希值再经过某种算法之后,计算到的结果就是key在Entry[]数组中存放的位置;
- 如果此位置上的数据为空,那么就直接添加;
- 如果此位置上已有数据,那么比较key和已有数据(可能会有多个,以链表的形式存储)的哈希值,如果哈希值都不同,那么添加成功;如果哈希值也相同,那么调用key所在类的equals()方法。
- 如果equals()方法返回false,则添加成功;如果返回true,则用value替换之前的值。
在不断的添加过程中,如果要添加元素的长度大于临界值时,并且要添加的位置非空,那么就扩容。默认扩容为原来长度的2倍,并且将原有的数据都复制过来。
HashMap底层实现原理(jdk8):
- HashMap map = new HashMap(); 实例化HashMap时,底层并没有创建长度为16的数组。
- jdk8底层数组是Node[],而非Entry[]。
- 首次调用put()时,底层创建长度为16的数组。
- jdk7的底层是数组+链表;jdk8的底层是数组+链表+红黑树。
- 当形成链表时,jdk7中是新的元素指向旧的元素。jdk8中是旧的元素指向新的元素。
- 当数组某一索引位置上的元素以链表存储的长度>8且当前数组的长度>64时,索引位置上的数据使用红黑树存储。
HashMap源码关键参数:
-
DEFAULT_INITIAL_CAPACITY:HashMap默认容量,16。
-
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75。
-
threshold:扩容临界值=默认容量*加载因子=12。
-
TREEIFY_THRESHOLD:链表长度大于该值,转化为红黑树:8。
-
MIN_TREEIFY_CAPACITY:Node被树化时最小hash表容量:64。
本文介绍了Java中Map接口及其主要实现类的特点与区别,包括HashMap、LinkedHashMap、TreeMap、Hashtable和Properties等。详细解析了HashMap的底层实现原理,从JDK 7到JDK 8的变化,以及其内部数据结构的调整。

1117

被折叠的 条评论
为什么被折叠?



