Java容器集合——ArrayList和LinkedList

       在看完ArrayList(https://blog.csdn.net/qq_41773240/article/details/87616011)和LinkedList(https://blog.csdn.net/qq_41773240/article/details/87629601)的源码之后,对两个集合容器的底层实现、基本用法和特性都有了基本的了解,接下来对两个容器进行总结和对比。

1.继承和接口关系

ArrayList继承了List接口的直接实现类AbstractList类,并实现了List、RandomAccess、Cloneable和Serializable接口。

LinkedList继承了AbstractList为了方便链表操作而派生的子类AbstractSequentialList类,并实现了List、Deque、Cloneable和Serializable接口。

从接口实现来看,两者都可以进行克隆和序列化,ArrayList可以进行随机访问,而LinkedList除了实现了List的基本功能外还能实现了双端队列的功能。

2.底层实现及数据结构

ArrayList使用动态增减的数组结构实现,LinkedList使用链表结构实现。

3.性能

(1)查找:ArrayList使用数组实现,因此可以通过索引快速查找到相应元素;而LinkedList则只能进行遍历,尽管LinkedList在遍历时会根据给出的索引序号是否大于链表长度一半来决定是否从链表最后向前遍历,但是速度肯定没有数组索引快。

(2)插入/删除:ArrayList插入元素时使用System.arraycopy方法将插入位置之后的所有元素都向后移一位,再将插入的元素插入至索引位,因此一次插入会引起很多元素位置的移动,效率较低,如果插入的位置靠后,那么被移动的元素就少,这样效率更高;而LinkedList只需改变插入结点即其前后结点的链接信息,不必牵一发动全身,总的来说效率较高,但是如果插入位置在中间,那么通过遍历找到位置的时间会更长,效率降低;删除同理。

(3)空间:ArrayList每次增长数组容量都至少增长原来的一半长度,因此很可能造成空间的浪费;LinkedList不会造成空间的浪费,但是会花费更多空间存储结点的信息。

(4)遍历:两者都可以使用foreach、iterator、for三种方式进行遍历

foreach方式:

List<Integer> list = new ArrayList<Integer>();
for (Integer j : list) {
	// use j
}

iterator方式:

List<Integer> list = new ArrayList<Integer>();
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
	iterator.next();
}

for方式:

List<Integer> list = new ArrayList<Integer>();
for (int j = 0; j < list.size(); j++) {
	list.get(j);
}

由于foreach和iterator都是从集合中一个一个拿出元素的,而for循环需要用到get方法,而get方法对于ArrayList来说是通过索引取出元素,影响不大,但对于LinkedList来说,get方法相当于再次遍历查找,复杂度大大提高,因此对于LinkedList来说一定不要用for循环+get的方法遍历,尽量都使用foreach或iterator进行遍历。

4.应用场景

ArrayList用于需要快速查找,简单添加的场景;LinkedList用于增删改较频繁,查找要求较低的场景。

猜你喜欢

转载自blog.csdn.net/qq_41773240/article/details/87692115