IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 程序优化之数据结构(List的数据结构的选择) -> 正文阅读

[数据结构与算法]程序优化之数据结构(List的数据结构的选择)

1.Arrarlist 和 Linkedlist 区别

(1)ArrayList 是实现了基于动态数组的数据结构,LinkedList 基于链表的数据结构。 (2)对于随机访问 get 和 set,ArrayList 觉得优于 LinkedList,因为 LinkedList 要移动指针。 (3)对于新增和删除操作 add 和 remove,LinedList 比较占优势,因为 ArrayList 要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList 的速度反而优于 LinkedList。 但若是批量随机的插入删除数据,LinkedList 的速度大大优于 ArrayList. 因为 ArrayList 每插入 一条数据,要移动插入点及之后的所有数据。(4)ArrayList?底层实现就是数组,且ArrayList实现了RandomAccess,表示它能快速随机访问存储的元素,通过下标?index?访问,只是我们需要用?get()?方法的形式,?数组支持随机访问, 查询速度快, 增删元素慢;LinkedList?底层实现是链表,?LinkedList?没有实现?RandomAccess?接口,链表支持顺序访问, 查询速度慢, 增删元素快。

2.Arrarlist和Vector的区别是什么?

(1)Vector的方法都是同步的,是线程安全的,而ArrayList的方法不是,由于线程的同步必然要影响性能;(2)当Vector或ArrayList中的元素超过它的初始大小时,Vector会将容量翻倍,ArrayList只增加50%的大小等。

3.list的安全性考虑(Collections.synchronizedList(new ArrayList<>())与CopyOnWriteArrayList)

ArrayList是不安全的,并发读写,会抛出异常。因此引入了CopyOnWriteArrayList。

CopyOnWriteArrayList

CopyOnWriteArrayList是ArrayList的一种线程安全的变体,在add、set、remove等会改变其内部值和长度的时候会通过创建一个新的数组来进行实现。对于CopyOnWriteArrayList来说,读的时候不加锁,只有在写的时候才加锁,适用于读操作远远大于写操作、而且不希望读的时候也去加锁,不希望在同步遍历时受到其他并发线程的干扰而错误错误的场景。在这种场景下使用CopyOnWriteArrayList非常适合。

?优点:?对于一些读多写少的数据,这种做法的确很不错,例如配置、黑名单、物流地址等变化非常少的数据,这是一种无锁的实现。可以帮我们实现程序更高的并发。

缺点:这种实现只是保证数据的最终一致性,在添加到拷贝数据而还没进行替换的时候,读到的仍然是旧数据。如果对象比较大,频繁地进行替换会消耗内存,从而引发Java的GC问题。

List<?> list = Collections.synchronizedList(new ArrayList<>());也可以保证安全性

Collections.synchronizedList(new ArrayList<>());使用的过程中遇到的陷阱。

4.真实场景的例子:

@NotThreadSafe
class BadListHelper <E> {
??? public List<E> list = Collections.synchronizedList(new ArrayList<E>());
??? public synchronized boolean putIfAbsent(E x) {
??????? boolean absent = !list.contains(x);
??????? if (absent)
??????????? list.add(x);
??????? return absent;
??? }
}

虽然说putIfAbsent方法加了synchronized的锁关键字,但是这个putIfAbsent方法获得锁和list对象的获得锁不是同一个锁;

putIfAbsent获得锁是BadListHelper这个类的锁对象,list获得锁对象是list;如果这么写,那list依旧能够被其他线程获取锁对象来改变list对象的值,就会导致数据出错,或者两两线程在访问这个方法的时候拿到的list数据可能会有错误;所以这么写是不对的;要想保证list数据不出错,就要给他自己上锁,其他线程将不能获得list锁来来改变list对象。

@ThreadSafe
class GoodListHelper <E> {
??? public List<E> list = Collections.synchronizedList(new ArrayList<E>());
??? public boolean putIfAbsent(E x) {
??????? synchronized (list) {? //获得list锁对象,其他线程将不能获得list锁来来改变list对象。
??????????? boolean absent = !list.contains(x);
??????????? if (absent)
??????????????? list.add(x);
??????????? return absent;
??????? }
??? }
}

5.Collections.synchronizedList(new ArrayList<>())与CopyOnWriteArrayList使用对比:

Collections.synchronizedList(new ArrayList):读写删除加锁,且加锁在代码块上,效率较好,遍历未加锁,可以根据实际业务需求,自行决定是否加锁。

CopyOnWriteArrayList:读未加锁,写使用CAS自旋锁,先复制原数组,修改复制的数组,之后把复制数组重新复制给原地址(当数组过大时,复制效率极低),并发过多,CAS碰撞过多,也会影响性能,读取数据是原数组,所以如果add方法还未执行到setArray方法,读取的数据就是原来的数据。
?

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 11:07:37  更:2022-08-06 11:10:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:26:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码