java基础:集合

笼统地说:
Collection:
List:

  • ArrayList:可变、数组、不同步、允许null,相较于LinkedList查询快(有索引的存在)
  • LinkedList:链表,允许null,不同步,增删改快于ArrayList。
  • vector:类似ArrayList,同步。
  • stack:堆栈,继承自vector,同步.

Set:

  • hashset:不允许重复,不保证顺序,允许null,不同步。
  • treeset:升序排列,性能不如hashset。

Map:

  • hashmap:不同步,允许null(key和value),无序
  • hashtable:同步,不允许null,无序,
  • ConcurrentHashMap:同步(分段锁),底层是数组+链表

网上看到的解释
网上看到的解释

哈希碰撞解决方法:

开放定址法: 比如说key算出来的哈希地址p=H(key)出现冲突,那就以p为基础再去哈希算法算一次p1哈希地址,再冲突再算,算到不冲突为止。

再哈希法:当第一个哈希函数算出来冲突时,换另一个哈希函数去算。这种方法不易产生聚集,但是增加计算时间。

链地址法(也叫拉链法):如果说有好几个都冲突了,那就把这几个元素构成单链表,冲突就加在后面,这种方法适用于经常插入和删除的情况。

HashMap,HashSet其实都是采用的拉链法来解决哈希冲突的。但是问题是,如果冲突得很厉害,就有可能退化成单链表,因此JDK1.8之后加入红黑树,如果我这个链条(称为位桶)超过16,那就转换成红黑树。

红黑树:https://zhuanlan.zhihu.com/p/79980618?utm_source=cn.wiz.note

二叉树、平衡二叉树、红黑树、B树、B+树与B*树:https://www.jianshu.com/p/b597aa97c9de

但是如果默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。因此,如果预估容量是100,即需要设定100/0.75=134的数组大小。此时扩容在重新计算哈希的时候有可能会出现死锁的情况。

为什么扩容是2倍,为什么会死锁:

static int indexFor(int h, int length) {

return h & (length-1);

}

首先要了解的是,元素确定放在那个地方,其实是算出哈希值(比如说算出是1111),哈希值和数组长度-1进行与运算(比如说长度是16,-1是01111),算出来索引位置是15。

那么我假设长度是15也就是1111,-1就是1110,那么可以看到,无论哈希值是多少,第四位与出来的结果一定是0,也就是说分布会不均匀,会增加碰撞的几率和造成空间的浪费。

那么死锁就是扩容的时候,重新进行哈希计算,遍历旧数组,将旧数组元素通过头插法的方式,迁移到新数组的。经过这几步会发现转移的时候是逆序的,A->B->C迁移后会变成C->B->A,HashMap 的死锁问题就出在这个transfer()函数上。

假设有个链表顺序是AB,算出来有可能哈希值还是一样,那么扩容的时候链表回事BA,但是假设有2个线程同时进行,第1个线程执行Entry<K,V> next = e.next;简单的说就是算出B指向A,但是原本A指向B应当改成A指向null,但是没有改。

最后会造成A指向B,B指向A的神奇操作。(讲的好烂,给个链接好了https://blog.csdn.net/chenyiminnanjing/article/details/82706942

1.8之后就不用头插法改用尾插法了,同时用链表+红黑树的方式。

JDK1.7和1.8中hashmap的区别:

  1. 底层结构不一样,1.7是数组+链表,1.8则是数组+链表+红黑树结构。
  2. put方法的区别,1.7中是采用头插法,1.8采用尾插法(也就是会将节点插入到链表尾部)。
  3. 1.7中,当哈希表为空时,会先初始化一个数组,1.8是直接使用resize()扩容。

貌似还有更多。

hashtable和ConcurrentHashMap

hashtable在修改数据的时候锁住整个hashtable,因此ConcurrentHashMap做了相关优化,做法就是分段锁。首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

Vector和ArrayList和LinkedList

这两个都实现了list接口。这两个都是通过数组实现,都是vector是支持线程同步的,也就是同一时刻只有一个线程能够写vector。
同时vector实现了Serializable接口,因此可以进行序列化。

个人收藏的网址:
java集合超详解:https://blog.csdn.net/feiyanaffection/article/details/81394745
ArrayList详解:https://blog.csdn.net/sihai12345/article/details/79382649
Map的用法:https://blog.csdn.net/qq_29373285/article/details/81487594
Vector:https://blog.csdn.net/qq924862077/article/details/48039567
Vector菜鸟教程:https://www.runoob.com/java/java-vector-class.html
Vector和ArrayList的区别:https://www.cnblogs.com/zhangzongle/p/5432212.html
ConcurrentHashMap底层原理?:https://segmentfault.com/a/1190000022533242
HashMap、Hashtable、ConcurrentHashMap的原理与区别:https://www.cnblogs.com/heyonggang/p/9112731.html
HashMap put方法的流程:https://blog.csdn.net/weixin_42118284/article/details/100114394
linkedlist和arraylist的区别是什么:https://m.php.cn/faq/415621.html
解决哈希冲突的常用方法有哪些?:https://blog.csdn.net/weixin_43258908/article/details/89252871

(最近才开始写博客,排版什么的还有很多问题,内容上也不敢说是绝对正确的,有不足的地方请各位大佬帮忙斧正,内容多为网上资料加上一点点自己的理解,侵删,谢谢!)
实在是没啥经验,标题都不会取,评论区有大佬和给点建议吗

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值