java插入图片_程序员练级,轻松搞懂Java集合类LinkedList数据结构及实现原理

Java是后端程序员的一门必修课,Java 开发非常方便,针对通用场景的需求, Java 提供了强大的集合框架,大大提高了开发者的生产力。本章透过源码分析了Java集合类之一的LinkedList。

0b726d79a6d74764493f7337a643e442.png

图1

LinkedList

LinkedList 是Java提供的双向链表 ,它不需要像Vector和ArrayList那样调整容量,它也不是线程安全的;如下图2和图3源码;

11eaf0946f92bdbbca173bd25bdd979e.png

图2

634d094f322de8020b53cb68b9565546.png

图3

不同容器类型适合的场景

(1)Vector和ArrayList

Vector和ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。

(2)LinkedList

而LinkedList进行节点插入、删除却要高效得多,但是随机访问性能则要比动态数组慢。所以,在应用开发中,如果事先可以估计到,应用操作是偏向于插入、删除,还是随机访问较多,就可以针对性的进行选择。

LinkedList对操作元素

插入:

LinkedList在插入元素时,须创建一个新的Entry对象,并更新相应元素的前后元素的引用;

e9c7671fb0ec0b443919231fce9ef79c.png

图4

60a4c4fe9bb1f54c71661ce584b35d93.png

图5

查找:

在查找元素时,需遍历链表;

如下图6,图7,图8 ;先检查索引是否符合LinkedList要求;

23acf1ea88ffd2b4ead752ada176fe2e.png

图6

596dc5192ba8ac08902a8b9bfcc86b9f.png

图7

f417c651a3ca3aa2d2f3999332b5c5aa.png

图8

遍历链表

cb6e1e268dd8f8d7455701c94dd1f916.png

图8

删除:

在删除元素时,要遍历链表,找到要删除的元素,然后从链表上将此元素删除即可。

如图按照对象删除源代码:

b439a77edb3fa2b6b5da56718ca54d90.png

图9

扩容机制

Vector与ArrayList仅在插入元素时容量扩充机制不一致。对于Vector,默认创建一个大小为10的Object数组,并将capacityIncrement设置为0;当插入元素数组大小不够时,如果capacityIncrement大于0,则将Object数组的大小扩大为现有size+capacityIncrement;如果capacityIncrement<=0,则将Object数组的大小扩大为现有大小的2倍。

效率分析

LinkedList由于基于链表方式存放数据,增加和删除元素的速度较快,但是检索速度较慢。

线程安全问题

LinkedList是非线程安全的,线程安全问题是由多个线程同时写或同时读写同一个资源造成的。

为什么不安全?

简单举例分析启动一个部分,如下图,当多个线程同时对一个LinkedList对象进行添加操作的时候如果线程A执行last = newNode后时间片停止,然后线程B执行last = newNode后时间片也停止。A从新开始执行,其实这个时候B已经改变了LinkedList的结构,但是线程A不知道继续执行,导致A执行后的数据出现错误,随后B执行的数据也会以出现错误。

6345a096317e4d1882c3f20d27f14f3c.png

图10

ef2476bbde7c94d7f7d13d9050a36791.png

图11

使用建议:

单线程应尽量使用ArrayList,LinkedList。Vector因为同步会有性能损耗,目前早已经不推荐使用,建议多线程关注线程集合类,如PriorityBlockingQueue,ArrayBlockingQueue

,BlockingDeque等;

2a0e5ab008e3752f6f2499ddbc36fd15.png

图12

Java集合类是如何体现数据结构的?

如下图我们可以看到集合数据结构的体现在共性上,List,Queue

54918d9cc148d040d0c5fab859967dc2.png

图13

注意细节

Vector和ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。而LinkedList进行节点插入、删除却要高效得多,但是随机访问性能则要比动态数组慢。

很多人盲目的选择LinkedList,因为LinkedList适合插入效率高的场景,但是一定要注意Vector和ArrayList在尾部增删都不会会开辟新内存,效率也是非常高的,如果你的场景是这种情况,用LinkedList反而失去了查询效率。

2212eca8c1a5549a4d68b7a6c3a74cd7.png

图14

编译放代码容易乱,所以截取少量图片,大家可以打开编译器自己去看代码,将你的新的总结发布到下发评论和大家一起分享吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值