java即时通讯框架比较_Java集合框架比较

ArraryList和 LinkedList区别

是否是线程安全:

2者都不是线程安全的;

底层数据结构:

ArraryList 是使用Object[]数组;

LinkedList底层使用的是双向链表(jdk1.6之前是循环头尾相连,jdk1.7之后是取消了循环);

插入和删除是否受元素位置影响:

ArrayList采用数组存储,所以插入和删除元素的时间复杂度受元素位置影响。如果是追加到列表的末尾,那时间复杂度是0(1),如果要在指定位置i插入和删除元素时间复杂度为0(n-i)。因为要移动元素位置。

LinkedList采用链表存储,在删除或插入数据时复杂度都是0(1),如果要在指定位置i插入和删除元素时间复杂度0(n),因为需要先移动到指定位置再插入。

是否支持快速随机访问:

LinkedList不支持高效的随机元素访问;

ArrayList支持快速随机访问,通过序号快速获取元素对象;

内存空间占用:

ArrayList的空间浪费主要体现在List列表的结尾会预留一定容量;

LinkedList的空间花费则体现在他的每一个元素需要消耗比ArrayList更多的空间;

ArrayList扩容机制

ArrayList里面有2个概念,一个是capacity,他本质就是数组elementData长度。另外一个size指的是已经存放元素的个数。

默认情况下,新扩容会是原容量的1.5倍,为了防止频繁扩容影响性能。

如果自己清楚知道自己需要的数组长度,那么可以手动扩容,避免自动扩容多次造成的性能损失。

HashSet如何检测重复

当对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时会与其他已经加入的对象的hashcode值比较,如果没有相符的hashcode,hashSet会假设对象没有重复出现。若检测到相同的hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否是真的相同。如果相同,则不会再次加入。

hashCode()与equals():

如果2个对象相等,则hashcode是相同的;

2个对象相等,那么equals方法返回true;

2个对象的hashcode值相同,他们不一定是相等;

equals方法被覆盖过,则hashcode方法必须被覆盖;

hashCode()的默认行为是对堆上的对象产生独特的值。如没重写hashCode(),则class的2个对象无论如何都不会相等;

==与equals区别

对于基本类型,==比较的是值是否相等;

对于引用类型来说,==比较的是2个引用是否指向同一个对象地址;

对引用类型,equals如没被重写,对比的是地址是否相等;若equals()被重写,比较的是地址里面的内容;

HashMap实现

JDK1.8之前:

hashMap底层是数组和链表 结合一起的。hashMap通过key的hashCode经过扰动函数处理过后得到hash值,然后通过(n-1)&hash判断当前元素位置(n是指数组长度),如果当前位置存在元素,就判断该元素与要存入的元素的hash以及key是否相同,如果相同直接覆盖,不相同就通过拉链法解决冲突。

所谓扰动函数指HashMap的hash方法,为了防止一些实现比较差的hashCode()方法,而使用扰动函数后可以减少碰撞。

JDK1.8之后:

当链表长度大于阈值(默认8,将链表转成红黑树前,如果当前数组的长度小于64,那么会先进行数组扩容,而不是转成红黑树),将链表转化为红黑树,减少搜索时间。

HashMap长度为什么是2的幂次方

取余(%)操作如果余数是2的幂次方,那么等于与其除数减一的与(&)操作,即hash%length == hash & (length - 1)的前提是length是2的幂次方。且采用位操作&,相对于%取余能提高运算效率。这就是hashMap的长度是2幂次方原因

hashMap多线程操作导致死循环问题

主要原因是并发下的Rehash会造成元素之间会形成一个循环链表。在1.8过后已经解决,但还有其他并发问题,并发环境下还是最好用ConcurrentHashMap。

ConcurrentHashMap

JDK1.8之前:

底层采用Segment分段数组+HashEntry数组+链表实现;分段锁对整个桶数组进行了分割分段,每一个锁只锁容器中一部分数据,在多线程访问其他数据段时不存在锁竞争。

Segment的结构和HashMap类似,是一种数组和链表结构,一个Segment包含一个HashEntry数组,每个HashEntry是一个链表结构元素,每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须先获取对应的Segment锁。

Jdk1.8之后:

底层采用数组+链表/红黑二叉数。并发采用synchronized和CAS操作。

synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率有大幅提升。

c9d388ffdddf13968e8375ba3f0be333.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值