java list主要实现_java容器-list的常用实现及原理

list是个一唯的线性存储容器。我们可以把它比喻成一个竹签子,你可以把山楂、橘子串在上面,也可以把鸡翅、羊肉串在上面。吃的时候你可以从头、尾或者中间任何地方下口。

我们下面着重介绍下两个常用的实现,ArrayList和LinkedList。

ArrayList

arraylist顾明思议就是通过数组这种数据结构实现的list。数组的实现可以让它从任意的位置读取数据,也可以把数据写入数组的任意位置,但由于数组需要指定长度,所以会有扩容的问题。

LinkedList

LinkedList是通过链表实现的list。它的每个节点都会存储前一个和后一个节点的指针,每个list还会存储头和尾两个指针,所以它不能直接读取指定位置,但不会有扩容的问题。

list的主要场景有4个,顺序写、随机写、顺序读和随机读,下面我们从这4个场景模拟分析下这两种实现的不同点。

1.顺序写

ArrayList

//我们先初始化一个ArrayList, 这时arraylist会帮我们初始化一个长度为10的数组

List list = new ArrayList();

因为数组初始化必须指定长度,所以我们创建ArrayList时就会创建一个定长数组。

6383538102370f042121eae467c8c178.png

//这时我们把调用add方法把1写入到list中

list.add("A");

因为arraylist会保存index,所以add方法只是把数组的index位赋值为A,index加1就可以了。

7124b5433322570cab81631fdfab57b3.png

//这时我们把调用add方法把B写入到list中

list.add("B");

填加B也是同理

02c6796a578b8d86a0da4fe0d4ac7ac7.png

LinkedList

//我们先初始化一个LinkedList,初始化时LinkedList并不会做什么

List list = new LinkedList();

//这时我们把调用add方法把A写入到list中

list.add("A");

这时的linkedlist的头指针和尾指针同时指向A

5886225bcee6b29ad23b9cbf1c248764.png

//我们再调用add方法把B写入到list中

list.add("B");

当调用add方法时,因为尾指针指向的是A节点,所以把A节点的next节点指向B,同时尾节点指向B

e37676737b948159fd16fb30e44d3749.png

2.随机写

Arraylist

e2dda6cf51612072918dd0d2e898d2c0.png

//我们再调用add方法把C写入到list中

list.add(2, "C");

007c0aa84120eb5845a3ca5ea511d967.png

所以ArrayList的随机写时间复杂度为O(n)

LinkedList

4656f8fb4d8ceed893ecb11c52cd2789.png

//我们再调用add方法把C写入到list中

list.add(2, "C");

8e9908a2bd7649b91477ac41af17ecc7.png

linkedlist虽然不需要做节点移动,但是他要通过A、B、D节点这样遍历的方式找打插入的位置,所以时间复杂度也为O(n)

3.顺序读

Arraylist

在访问arraylist中任意一个元素的时候,因为底层实现是数组,所以都可以直接读取,时间复杂度为O(1)。

LinkedList

使用迭代器读取linkedlist,迭代器会维护一个当前节点的指针,所以也不需要循环查找,时间复杂度为O(1)。

4.随机读

Arraylist

arraylist的随机读通过底层数组支持,时间复杂度为O(1)。

LinkedList

linkedlist的随机读则只能通过从头循环遍历的方式查找,所以时间复杂度为O(n)

5.ArrayList的扩容

数组因为长度固定,所以当数组已经存满的时候就需要扩容。

379ac84a654f3b7ce13316ca143df97d.png

如图所示,当D插入到arraylist时,发现数组已满,这时arraylist就会新建一个数组,长度是原来的2倍,并把原数组的数据移动到新数组,再把D插入到新数组中。

最后我们对比下这两个实现的时间复杂度。

时间复杂度

ArrayList

LinkedList

顺序写

O(1)

O(1)

随机写

O(n)

O(n)

顺序读

O(1)

O(1)

随机读

O(1)

O(n)

总结下我们应该如果选择

如果数据大小固定,需要随机读取使用ArrayList

如果数据大小不确定,不需要随机读取,使用LinkedList


版权声明:本文为weixin_36357218原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。