【十 薇:PPS33A】【任意挑选】【质量有保障】本场 Chat 分享主要介绍 Java 中的 Map 集合中的 HashMap、TreeMap。将从源码进行分析,避免一些人只听其说,不知其理,从而让读者深层次的理解 HashMap 的底层原理与实现。 本场 Chat 内容将涉及如下: Map 接口及常用方法; Map 接口及其子接口; HashMap 在 JDK7 中实现原理; LinkedHashMap 的底层实现原理; HashMap 在 JDK8 中相较于 JDK7 在底层实现方面的不同; TreeMap 的实现; 使用 Properties 读取配置文件。 当前内容版权归码字科技所有并授权显示,盗版必究。
文章正文
Map(双列集合框架)
1、Map 接口及实现类概述
Map 接口:存储的是一对一对的数据:key-value
HashMap:主要实现类;线程不安全的,效率高;允许添加 null 的 key 或 null 的 value
LinkedHashMap:是 HashMap 的子类,可以实现照添加的顺序实现遍历。(因为使用了一对双向链表记录添加元素的先后顺序),对于频繁的遍历操作,建议使用此类。
TreeMap:可以照元素 key 的指定的属性的大小实现遍历。底层使用红黑树实现。
Hashtable:古老实现类;线程安全的,效率低;不允许添加 null 的 key 或 null 的 value
Properties:常用来处理属性文件。key 和 value 都是 String 类型。
2、常用实现类结构
????在这里插入图片描述 ????
3、关于对 Map的理解
Map 中的 key 是无序的、不可重复的。key 构成的集合是 Set --->需要重写必要的 hashCode()和 equals()。
Map 中的 value 是无序的、可重复的。value 构成的集合是 Collection --->需要重写必要的 equals()。 Map 中的一个键值对构成一个 entry。
Map 中的 entry 是无序的、不可重复的。entry 构成的集合是 Set。
如图: 在这里插入图片描述
4、常用方法
增:put(Object key,Object value) 删:remove(Object key) 改:put(Object key,Object value) 查:get(Object key) 长度:size() 遍历:keySet() 、 values()、entrySet()
5、内部结构实现原理
很重要,必须要掌握。
5.1 HashMap 在 jdk7 中实现原理:
HashMap map = new HashMap();//Entry[] table = new Entry[16]; … map.put(key1,value1);// key1,value1 会封装在一个 entry 对象中。将此对象存放到 table 数组中 将 key1,value1 添加到 table 中,首先根据 key1 所在类的 hashCode()方法,计算 key1 的哈希值 1,然后使用某种算法,得到哈希值 2。 哈希值 2 再使用 indexFor()方法得到其在底层 table 数组中的存放位置:index。(0<= index <= 15)
如果 index 位置上没元素,则 key1,value1 直接添加成功。----添加成功操作 1
如果 index 位置上元素(key2,value2)(或已经存在一个链表结构),则比较 key1 和 key2(或链表上每个 key 的哈希值.
如果二者(或比较多个 key 以后)的哈希值不同,则(key1,value1)添加成功。 ----添加成功操作 2
如果二者的哈希值相同,则调用 key1 所在类的 equals(),将 key2 作为参数传递到此方法中,比较两个 key 是否 equals
如果返回值为 false:则(key1,value1)添加成功。----添加成功操作 3
如果返回值为 true:则 value1 替换原 key2 对应的 value2. ----修改成功
说明:添加成功操作 1:将 key1,value1 存放到数组的位置上。 添加成功操作 2,添加成功操作 3:将 key1,value1 添加到链表上。存放到链表头部
扩容的情况:当添加的数据达到临界值(= 数组的长度 * 加载因子)时,则进行扩容。默认的临界值为:16 * 0.75 = 12。默认扩容为原来的 2 倍。
数组的长度:DEFAULTINITIALCAPACITY:16 加载因子:DEFAULTLOADFACTOR:0.75 threshold:临界值 = 数组的长度 capacity * 加载因子 loadFactor。
5.2 HashMap 在 jdk8 中相较于 jdk7 在底层实现方面的不同:
jdk 8:数组+单向链表+红黑树
当使用空参的构造器,创建对象时,底层并没创建长度为 16 的数组。
当我们首次调用 put()添加数据时,底层会首先创建长度为 16 的数组。
底层创建的数组为:Node[]. (class Node implements Map.Entry)。
当某个索引位置上的链表长度>8,且数组的总长度>64 时,将此索引位置上的元素修改为使用红黑树进行存储。
形成链表时,新添加的元素在链表的结尾。
原文地址:https://www.cnblogs.com/jenixbsk/p/12160776.html