文章目录
前言
博客仅记录个人学习进度和一些查缺补漏。
学习内容:BV17F411T7Ao
一、双列集合
相比单列集合SET,双列集合每次存储一堆键值对
顶层接口MAP
常见API
首先使用多态将MAP用HashMap来实例化
使用put方法放入数据
后添加的键值对会覆盖前面添加的键值对,如果产生了覆盖,则返回被覆盖的值。
删除方法通过指定的键来删除对应的键值对,并且返回对应的值
包含判断,如果存在返回true,不存在返回false
遍历方法
方法一:先将所有的键找出来放进单列集合中,然后遍历该单列集合,并在遍历中找到对应的值
1、获取所有键,放入集合
keySet方法会直接返回键集合
2、遍历该单列集合,得到每一个键
3、利用键获取对应的值
方法二:
直接获取键值对对象
通过entrySet方法获得所有的键值对对象,并放入一个单列集合中
注意此时Set的泛型是entry,而entry做一个键值对对象,其泛型是调用它的对象对应的泛型
方法三:lamdba表达式进行遍历
此时,forEach方法的对象是BiConsumer类型,其他都不变
HashMap
每次存储都是先把键值对放到entry里,再根据键来计算哈希值,挂载到哈希表上
和单列集合基本一样。
先使用随机数创建投票结果
使用map来处理多项选择计数。
Linked Hash Map
底层原理还是哈希表,但是添加元素的时候会增加一个双向链表来存储元素挂载顺序。
put方法仍然具有覆盖功能,并且能保证存取顺序一致。
TreeMap
又是一个红黑树结构,具有良好的增删性能
排序以比较器对象规则优先。
默认按照键的排序规则来进行排列输出。
也可以按照比较器来进行比较,但是注意应该仅比较键。
经典例题:字符统计
统计–>计数器思想,但是如果统计的东西过多或者不确定数量,那么就无法使用计数器思想。
但是如果使用map集合进行统计,就可以解决上述问题
HashMap和TreeMap都可以用来统计,一般来说HashMap效率更高,但是HashMap没有排序,如果需要对键进行排序,就要使用TreeMap。
二、HashMap源码解析
ctrl+b跳转,ctrl+f12查看所有方法
上箭头表示重写,右箭头表示继承自。
c表示内部类
例如Node,实现了Entry类及其功能。
f 表示hashmap的属性
hash表的node节点,hash表作为顺序表,实际上是node数组
红黑树节点,当挂载大于64的时候出现
依次是数组默认长度(16) 最大容量(2^29),填装因子。
空参构造时仅初始化填装因子,数组的创建在添加元素时进行。
很明显在计算哈希值的时候没有出现值,说明哈希值仅和键有关
重复的时候是否覆盖
内部方法详解
内部类属性
添加元素方法
定义局部用来存储哈希表的地址值,虽然在HashMap的成员变量中已经指明了所使用的数组的地址,但是这个成员变量时存储在堆区的,而方法都存储在栈区,出现频繁使用该地址的情况的时候,不如在栈内临时创建一个局部变量来承载数组地址,减少去堆里找数据的时间。
先判断数组长度和元素数量
表中还没有元素(或者说对应的位置上没有元素),就新建一个node挂到表中
如果出现了键不同值不同的情况(不覆盖需挂载)
循环寻找链表下第一个null节点,然后挂上去
如果出现了键相同值不同的情况(需要覆盖)
前面的过程都相同,但此时进入第二个判断时(此时没有到链表结尾但是已经出现了hash值相同的情况,所以需要判断具体的key值和value值是否相同)会break
e表示将要添加到的节点位置,如果此时e不为null,说明需要判断是否覆盖当前节点
三、TreeMap源码解析
TreeMap集合中,每一个对象实际上都是一个entry对象
默认是红色,此时添加新节点为黑色,后续会有相关调整。
添加元素默认是需要覆盖的。
插入第一个节点的情况(根节点)
插入后续节点的情况
传入比较器的情况:
确定添加节点的位置后,将节点进行插入并调用红黑树调整方法
这里就解释了,节点本身是黑色的(便于阅读),但是进行插入的时候默认是红色的。
四、可变参数
指定数量的求和很简单。
以前的方法求N个数和,但仍需要提前创建数组
虚拟机帮我们创建数组,这就是可变参数
其中args就是我们需要的那个数组。
需要注意,只能有一个可变参数,并且只能写在最后:
五、collections
集合的工具类,直接对集合进行操作。
批量添加:
就不用一个数据写一行add了
将集合内元素的顺序打乱,遍历的顺序就会改变。
总结