List底层结构

List的实现类常用的用

  • LinkedList
  • ArrayList
  • vector

LinkedList:线程不安全

底层结构是双向链表,开销在于需要存储结点信息以及结点指针信息。

在这里插入图片描述
双向链表是由三部分来组成的:prev、data、next

  • prev:存储上一个节点的地址
  • data:存储将要存储的数据
  • next:存储下一个节点的地址

在这里插入图片描述
双向链表的排序方式是没有顺序的;当我们新增一个元素时,只需要修改前一个元素的next和后一个元素的prev即可,删除元素同理;这样使得LinkedList对于新增和删除的效率大大提高。但是查询数据时,需要一个一个的查找,直到找到为止,使得查询的效率变得很低

get和set慢,add和remove更新快。

ArrayList:线程不安全

底层结构是可变数组,开销在于List列表预留一定空间。

数组存在的位置为在JVM的堆中,用来存储固定大小同类型元素的。当新的元素需要存储时,会存储在最前面,所以每次存储新元素时,所有的元素都会向后移动位置。同理,删除一个元素时,数组中所有的元素都会向前移动位置,所以ArrayList对于增删的效率很低。

数组里面的元素占用的内存相同并且连续排列的。在查询时可以根据数组的下标来进行快速访问,所以ArrayList对于查询效率高。

get和set快,add和remove更新慢。

扩容机制:

  1. 初始化容量10,初始最大容量Integer.MAX_VALUE - 8
  2. 先判断,加了新数据之后,原来的容量能不能放下
  3. 放不下的话,进入扩容方法
  4. 原容量*1.5(newCapacity = oldCapacity + (oldCapacity >> 1))
  5. 新容量与minCapacity比较,取较大的值,即扩容一次还不够,就按需取容量
  6. 如果新的容量超出了Integer.MAX_VALUE - 8,那就用Integer.MAX_VALUE

为什么Integer.MAX_VALUE - 8:

主要区别在于数组对象有一个额外的元数据,用于表示数组的大小。不只是数组的长度信息,还有数组对象的类信息还有同步信息

Vector:线程安全

大致与ArrayList保持一致,有以下几个区别

  • 每个方法上都加了synchronized的关键字来保证线程安全,效率降低
  • 扩容机制上,维护capacityIncrement增长系数,ArrayList是原容量*1.5,Vector采用newCapacity = oldCapacity + capacityIncrement > 0 ? capacityIncrement : oldCapacity。特就是说存在增长系数就直接加,没有的话就翻倍。

CopyOnWriteArrayList:线程安全

总体基于ArrayList,实现线程安全的方式:CopyOnWriteArrayList通过使用ReentrantLock锁来实现线程安全,写的时候获取副本进行修改,所以不影响读(读写分离)
区别在于:

  • 初始容量是0,每次扩容空间刚好够用,不会有多余的空间
  • 不能保证数据的实时一致性

Collections.SynchronizedList:线程安全

与Vector区别

  • 扩容机制不同,SynchronizedList与ArrayList一致
  • SynchronizedList锁代码块,并且可以选择锁的对象,Vector锁方法
  • SynchronizedList进行遍历的时候要手动加锁,Vector不用
  • SynchronizedList有很好的扩展和兼容功能。他可以将所有的List的子类转成线程安全的类。:LinkedList直接转成 SynchronizedList但不能转变成Vector,因为底层结构限制
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Redis 3.2版本之前,list底层数据结构使用了两种实现方式:压缩列表(zipList)和双向链表(LinkedList)。 压缩列表是一种紧凑的数据结构,可以同时存储多个元素,并根据需要动态地调整大小。它使用连续的内存空间存储元素,可以有效地节省内存。每个元素都有一个长度字段来记录其字节长度,以及一个编码字段来表示元素的类型。前一个元素的长度也通过prevlen字段记录。 双向链表是由节点组成的数据结构,每个节点包含一个指向前一个节点和后一个节点的指针,以及存储元素的内容。双向链表可以在任意位置插入或删除元素,具有灵活性和高效性。但是它占用更多的内存空间。 因此,在Redis中,list底层数据结构根据需要可以使用压缩列表或双向链表来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Redis底层数据结构List](https://blog.csdn.net/gongsenlin341/article/details/110527676)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [List底层结构](https://blog.csdn.net/weixin_38204723/article/details/122543621)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值