个人集合汇总(面试使用)

一.Map

最强hashmap源码:https://mp.weixin.qq.com/s/bjT9Uvyprgtk2IPMwt9SAA

经典:https://mp.weixin.qq.com/s/EoOqH9aBcO_OQBDj1X5pKA

hashMap hashTable concurrentHashMap

1.核心的常量:负载因子默认0.75(从查询性能和hash表所占内存开销两方面参考折中取值), 初 始化容量 16(二进制机制)都是2的幂次方。主要是length-1后的二进制都是111,相比1101,增加空间使用,减少碰撞记录,查询快;

当链表大于8时候转为红黑树

2.核心的方法:getNode putVaule resize

putvalue方法:当比较put的值得hashcode值,在使用== 和equals比较key,如果相等才替换

putvule中第一个hash指的是key的hash值,第二个是key的原值。先比较hashcode值在使用== 比较地址值确认替换不

3.扩容机制: 新建数据,将旧数据复制到新数组中

4.hashTable: 安全---方法都加锁了 synchronized 针对代码块,使用在put方法上,性能低

hashmap的key -value都可以为null,hashtable不能

hashtable是同步的,hashmap不是。所有hashmap适合单线程环境,hashtable适合多线程(安全)

5. concurrenthashMap:https://mp.weixin.qq.com/s/h6SMb1y7XVJa8jc-Xu3LYw

1.7版本---使用了分段锁机制,并发时只是对一个桶加锁,其他15个桶可以正常访问。segment

1.8版本---链表+数据+红黑树结构,采用cas(乐观锁机制)+锁住node,用sizectl值不同控制业务。cas就是不可能死锁,要么改变,要么循环继续执行盘点能否更改。

6.hashmap(int a,int b)校验初始化的容量值和加载因子的值

MAXIMUM_CAPACITY 容量最大值,当初始化超过时会取最大值。2*30 2的30次方,1073741824最大容量

HashMap的数据存储实现原理

流程:

1. 根据key计算得到key.hash = (h = k.hashCode()) ^ (h >>> 16);

2. 根据key.hash计算得到桶数组的索引index = key.hash & (table.length - 1),这样就找到该key的存放位置了:

① 如果该位置没有数据,用该数据新生成一个节点保存新数据,返回null;

② 如果该位置有数据是一个红黑树,那么执行相应的插入 / 更新操作;

③ 如果该位置有数据是一个链表,分两种情况一是该链表没有这个节点,另一个是该链表上有这个节点,注意这里判断的依据是key.hash是否一样:

如果该链表没有这个节点,那么采用尾插法新增节点保存新数据,返回null;如果该链表已经有这个节点了,那么找到该节点并更新新数据,返回老数据。

二.List

1.arrayList:初始化10容量,调用grow()方法扩容,每次1.5倍。将旧数据copyof()复制新数组中;查更快,操作少。

2.LinkedList:增删快,因为该的节点索引少。双向循环链表数据结构。不安全。

三.Set

1.HashSet:无序,不可重复。底层是hash实现,没有修改方法。存取快

2.TreeSet: 无序,不可重复。底层二叉树实现,

3.LinkedHashSet:差用hash表存储,双向链表结构。

 

总结:安全的就是带锁,vecoter,hashtable

四。iterater 和listiterator 区别

1.iterator 遍历list和set;只能向前遍历

listiterator:只能遍历list;可以双向遍历;继承了iterator接口,增加一些额外功能,例如增加一个元素,替换一个元素

五。遍历List不同方式;安全性

foreach it.hasNext

使用迭代器更加线程安全,且如果集合元素改变会抛错

六:hashMap 工作原理

HashMap在map.entry静态内部类实现中存储key-value对。在put时,用key,hashcode一些hash算法去查存储的key-value对的索引,如果entry存在就使用equals比较key值。如果存在覆盖vaule值,如果不存在创建一个新的entry。当get时,用hashcode找到数组中的索引,用equals找到entry,然后返回值。

所以:我们可以根据需求定义我们的初始容量。扩容时消耗内存。也是底层复制到新的数组中

七:任何类可以作为map的key:但是注意里面的hashcode和equals方法是否重写

八:hashmap问题:

为什么负载因子默认是0.75?按照官方给出的解释是,当负载因子为0.75时候,Entry单链表的长度几乎不可能超过8(到达8的概率是0.00000006),作用就是让Entry单链表的长度尽量小,让HashMap的查询效率尽可能高。

 

由于当HashMap的大小(即size)大于初始容量(capacity)时候,HashMap就会扩大一倍,由于很多时候并不需要扩大这么多,所以当我们知道我们的数据的大小的时候,就可以在HashMap初始化的时候指定容量(数组大小)。


需要注意的是,我们指定的容量必须是2的幂次方,即使我们传入的容量不是2的幂次方,源码中也会将容量转成2的幂次方,比如我们传入的是5,最终的容量是8。

 

为什么容量一定要是2的幂次方?因为HashMap是数组+单链表的结构,我们希望元素的存放的更均匀,最理想的状态是每个Entry中只存放一个元素,这样在查询的时候效率最高。那怎么才能均匀的存放呢?我们首先想到的是取模运算 哈希地址%容量大小,SUN的大师们的想法和我们的也一样,只不过他们使用位运算来实现这个运算(位运算效率高),为了使位运算和取模运算结果一样,即hash & (capacity - 1) == hash % capacity,容量(Capacity)的大小就必须为2的幂次方。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值