文章目录
- 1.linkedhashset的介绍
- 2.linkedhashset源码分析
- 3.Map的基本介绍
- 31.基本属性
- 3.2map里面的集合以及内部数据类型
- 4.Map接口的常见方法
- 5.map里面的遍历的方法
- 5.1根据key直接遍历
- 5.2直接拿到这个value值
- 5.3使用这个entry遍历
- 6.hashmap扩容转化红黑树的模拟
- 7.hashtable底层介绍
- 8.properties介绍
- 9.集合的选型规则
1.linkedhashset的介绍
下面的这个就是我们的linkedhashset的结构示意图,和我们之前介绍的这个hashset相比之下,这个linkedhashset的区别就是我们的这个linkedhashset是一个双向链表的结构;
下面的这个我们是首先插入了一个AA这个内容,然后是插入这个456,接着插入456这个时候可能计算这个hash值之后这个就无法继续插入了,因为这个已经存在了,我们创建一个新的对象,然后添加这个123,hsp这个字符串,在这个过程中,我们每一次添加一个元素,这个元素就会和上一个加入的数据构成双向的链表;
因此这个
插入和打印输出的顺序问题:我们上次介绍的这个hashmset插入数据的顺序和我们的打印输出的顺序是一致的,就是因为我们的这个链表是一个双向的链表,这个节点的顺序就是确定的;
2.linkedhashset源码分析
linkedhashset底层就是linkedhashmap(这个是hashmap的子类);
entry是这个底层的数据类型,table数组是这个node类型的,因此两者之间应该是存在某种关系的,table数组的最开始的大小就是16,和我们之前介绍的这个hashset最开始的空间大小是一样的;
我们的这个每一个数据entry就是我们的这个linkedhashmap的子类,因此我们的这个table数组是node类型的,我们的这个hashmap.node可以通过这个hashmap类进行访问,因此这个node类就是一个静态内部类(不属于对象,而是属于这个类,可以直接使用类进行访问)相当于这个entry是我们的这个hashmap下面的静态内部类node的一个子类;
下面的这个table就是我们的数组node类型的,0表示的就是数组下标entry类型的:
双向链表的节点之间连接方式,在这个调试过程中也是可以看到的,就是这个before和after,在我们插入第一个数据的时候,两个都是空的,当我们插入第二个数据的时候,这个里面的after就已经有了自己的指向,就不是null了,而是指向新的位置;
3.Map的基本介绍
31.基本属性
- map里面是有类似于这个键值对的内容组成的,key不可以重复,但是不同的key可以对应相同的value数值的;
- map里面的这个key可以是空的null,value也可以是null,但是我们的这个为null的key只能有一个,这个为null的value可以有多个;
- 通常情况下我们使用string,但是绝不仅仅只有这个string可以是我们的key,只要是object的子类就可以;
- 通过map.get方法可以得到这个对应的value数值,例如使用这个map.get(no1)就可以得到这个hsp这个value数值;
- 当插入的数据的key和已经存在的一样,但是这个value不一样的时候,这个新插入的数据会把原来的这个value替换掉,但是这个key不变化,因为两个是一样的;
- hashmap属于线程不安全操作;
我们的这个table还是数组,是node类型的,这个里面的数组元素是node类型的;
我们可以看到这个node实际上是实现了这个entry这个接口的,这个静态类里面包含了这个hash,key,value和我们的next指针指向下一个元素;
下面的这个就是数组是node类型的,我们通过转换为这个entry放到这个set里面去,然后这个set里面有这个set(引用)和collection方便对于我们的键和值进行管理;
下面的这个是往这个集合里面添加了两个基本的数据和这个new的对象;
我们可以看到,我们添加基本的数据的时候,还不可以从这个地址上面看到这个引用的关系,但是当我们new这个对象的时候,就会发现这个entryset里面的这个元素的地址和我们的这个table元素的这个对应的地址是一样的,因此可以证明这个就是一个引用的指向关系,这个entryset指向了这个hashmap$node里面的对应的位置;
3.2map里面的集合以及内部数据类型
深度分析:
- 第一次学习这个entryset的时候,也是非常的迷惑,其实这个entryset就是一个集合,这个结合里面的就是我们的这个entry数据;
- 我们知道在这个map里面,是有这个key-value组成的,我们下面的介绍就把这个key-value简称为这个k-v;
- 上面说到的这个entry实际上就是一个k-v,也就是说这个每一个entry都是一个k-v,然后这个所有的k-v组合在一起成为了entry这个集合;
- 上面的这个叙述转换为编码就是EntrySet<Map.Entry>,其中这个entryset里面的这个定义的类型是map.entry,但是这个实际上的存放的类型还是这个hashmap$node类型的数据;
- 为什么上面的这一点里面的存放数据的类型和我们的定义类型不一致,这个主要就是因为我们的这个hashmap n o d e 实现了这个 m a p . e n t r y 的接口,因此这个 h a s h m a p node实现了这个map.entry的接口,因此这个hashmap node实现了这个map.entry的接口,因此这个hashmapentry的实例化对象可以赋值给这个hashmap$node的接口(这个是接口的一个规则语法);
- 也就是说上面的这个图里面,我们的这个hashmap$node是实际存放的数据类型,但是这个会被转换为这个entry数据类型,然后放到我们的这个set里面去即可;
- 为什么会创建这个entryset集合,这个主要就是因为方便我们程序员进行这个集合的遍历,因为这个entryset里面有这个getValue和getKey的方法;
4.Map接口的常见方法
- map接口的方法,就是这个往集合里面放进去元素,使用这个put方法;
- 删除这个map的数据,使用的就是我们的这个remove方法;
- 清除键值对,可以使用这个clean方法;
- 可以使用这个iscontainkey判断是不是包含这个键;
- size方法可以用来获取这个集合里面的entry的个数,其中这个entry就是一个k-v;
5.map里面的遍历的方法
5.1根据key直接遍历
下面的就是使用增强for和迭代器两个方式,通过拿到这个key,使用这个对应的方法得到这个values;
5.2直接拿到这个value值
这个里面就是直接调用这个map.values方法得到这个values数值,然后使用两个方式进行这个结果的打印输出;
5.3使用这个entry遍历
我们下面的这个就是上面介绍的这个实现接口的是类的实例化对象可以传递给这个接口,但是我们需要把这个数据强制转换为这个map.entry类型的;
然后这个entry就可以去调用这个getkey和getvalue方法得到这个对应的键值情况;
6.hashmap扩容转化红黑树的模拟
hashmap扩容原理和之前的这个hahset完全一样;
这个主要是一个怎么样的过程呢?就是:
- 首先我们进行的这个类的定义的时候,返回值都是这个100,就是为了让他们计算的时候,数据都是在一个table的节点的这个链表上面,然后查看这个扩容的过程;
- 我们首先就是16个大小,添加这个元素的过程中,会伴随着两次的扩容的过程,一次就是16----32一次就是从这个32------->64的过程;
- 前面这两个扩容直到64的时候,这个节点的类型都是这个hashmap$node类型的,但是当我们的这个扩容达到了64之后继续插入数据,我们的节点的类型就是下面的这个显示的treenode类型的,这个时候已经是进行了这个红黑树的转化,这个就是树化的过程;
- 因此在这个元素的添加的过程中,先是进行这个table数组的扩容的操作,然后是这个达到64之后,转换成为这个hashmap$treenode节点类型的红黑树;
7.hashtable底层介绍
- 底层是这个hashtable$Entry[],初始化的大小是11;
- hashtable线程安全,不允许是null值;
- 下面的这个就是我们的hashtable的扩容的时候容量的变化:我们的这个原来的容量<<1表示的就是两倍+1即,这个扩容的过程就是在原来的这个11基础上面进行这个11*2+1=23的操作,因此这个扩容之后的大小就是23;
8.properties介绍
properties是我们的hashtable的子类,里面的这个数据也是k-v,里面数据也不可以是空的数据,如果相同的这个key后插入的这个value也会把原来的替换掉的;
properties通过这个get方法得到一个k-v里面的这个value数值,remove就是删除这个数据,因为两个相同的key也会把原来的value覆盖,因此可以使用插入相同的这个key去修改这个value数据内容;
9.集合的选型规则
学习了这么多的这个集合类型,我们如何进行选择:
首先判断这个是单列还是双列(k-v形式);
单列里面根据这个是否可以进行重复,分为了这个list和set结构,根据这个是否可以进行排序,分为了这个hashset和treeset结构;
在这个双列的结构里面,我们根据这个是不是有序的,是否可以进行排序,分为这个hashmap和treemap结构;