package com.study.java; import org.junit.jupiter.api.Test; import java.util.HashMap; /** * /----Map:双列数据 存储key-value对的数据 * /----HashMap:做为Map的主要实现类;线程不安全,效率高,存储null的key和value * /----LinkedHashMap:保证遍历map元素时,能够按添加顺序实现遍历 * 缘由:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。 * /----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的天然排序或订制排序 * 底层使用红黑树 * /----Hashtable:做为古老的实现类,线程安全,效率低;不能存储null的key和value * /----Properties:经常使用来处理配置文件。key和value都是string类型 * * * HashMap底层:数组+链表 (jdk7及之前) * 数组+链表+红黑树 (jdk8) * * Map结构的理解: * Map中的key:无序的、不可重复的,使用Set存储全部的key key所在的类要重写equals和hashCode方法 * Map中的value:无序的,可重复,使用Collection存储全部的value value所在类要重写equals方法 * 一个键值对:key-value构成一个Entry对象 * Map中的Entry:无序的、不可重复的,使用Set存储全部的entry * * * HashMap的底层实现原理,jdk7为例: * HashMap map = new HashMap(); * 在实例化后,底层建立了长度为16的一维数组Entry[]table * ...... * map.put(k1, v1) * 首先,调用k1所在类的hashcode()计算k1的哈希值,此哈希值通过某种算法计算后,获得Entry数组存放的位置 * 若是此位置上数据为空,此时K1-v1添加成功 * 若是此位置上的数据不为空,(意味着此位置上存放一个或多个数据(以链表形式存在)),比较k1和已经存在的一个或多个数据的哈希值:4 * 若是k1的哈希值和已经存在的数据哈希值都不相同,此时K1-v1添加成功。 状况1 * 若是k1的哈希值和已经存在的某一个数据(k2-v2)的哈希值相同,继续比较:调用k1所在类的equals(k2)方法,比较: * 若是equals返回false :添加成功 状况2 * 若是equals返回true:将v1替换相同key的value值 * 补充:关于状况2和状况3,此时key1-value1和原来的数据以链表的形式存储 * 在不断添加过程,会涉及扩容问题,默认扩容方式:扩容为原来容量的两倍,并将原有的数据复制过来 * * jdk8相较于jdk7在底层实现方面的不一样: * 1. new HashMap():底层没有建立一个长度为16的数组 * 2. jdk8 底层的数组是Node[],而非Entry[] * 3. 首次调用put方法时,底层建立长度为16的数组 * 4. jdk7底层结构:数组+链表 jdk8:数组+链表+红黑树 * 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 ,且当前数组的长度 > 64时, * 此时此索引位置上的全部数据改成使用红黑树存储。 * * DEFAULT_INITIAL_CAPACITY :HashMap的默认容量:16 * DEFAULT_LOAD_FACTOR :HashMap的默认加载因子:0.75 * threshold :扩容的临界值:=容量*填充因子:16 * 0.75 => 12 * TREEIFY_THRESHOLD:Bucket 中链表长度大于该默认值,转化为红黑树:8 * MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量 * * * LinkedHashMap的底层实现原理:,添加数据时,还维护了两个引用,记录前一个和后一个数据 * * TreeMap 中添加key-value,要求key必须是由同一个类建立的对象 * //由于要按照key进行排序:天然排序、订制排序 * * Properties:经常使用来处理配置文件。key和value都是string类型 */ public class MapTest { @Test public void test1() { HashMap hashMap = new HashMap(); hashMap.put(null, 123); hashMap.put(222, "aa"); hashMap.put(223, "bb"); System.out.println(hashMap); } @Test public void test2() { HashMap hashMap = new HashMap(); hashMap.put(null, 123); hashMap.put(222, "aa"); hashMap.put(223, "bb"); System.out.println(hashMap); } }