笼统地说:
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.7是数组+链表,1.8则是数组+链表+红黑树结构。
- put方法的区别,1.7中是采用头插法,1.8采用尾插法(也就是会将节点插入到链表尾部)。
- 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
(最近才开始写博客,排版什么的还有很多问题,内容上也不敢说是绝对正确的,有不足的地方请各位大佬帮忙斧正,内容多为网上资料加上一点点自己的理解,侵删,谢谢!)
实在是没啥经验,标题都不会取,评论区有大佬和给点建议吗