常见Java集合实现细节——ArrayList和LinkedList
2017-04-16 23:55
337 查看
3、ArrayList和LinkedList
在List集合的实现类中,主要有三个实现类:ArrayList、Vector、LinkedList。其中Vector还有一个Stack子类,这个Stack子类仅在Vector父类的基础之上增加了五个方法,这五个方法使得Vector扩展成为Stack。//stack源代码 public class Stack<E> extends Vector<E> { public Stack() { } public E push(E item) { addElement(item); return item; } public synchronized E pop() { E obj; int len = size(); obj = peek(); removeElementAt(len - 1); return obj; } public synchronized E peek() { int len = size(); if (len == 0) throw new EmptyStackException(); return elementAt(len - 1); } public boolean empty() { return size() == 0; } public synchronized int search(Object o) { int i = lastIndexOf(o); if (i >= 0) { return size() - i; } return -1; } }从上面的代码可以看出,Stack本质依然是一个Vector,并且是一个线程安全的类,因此Vector也是一个线程安全的类,只是增加了五个使用synchronized修饰的方法。
实际上,即使程序中需要这种数据结构,Java也不推荐使用Stack类,而是推荐使用Deque实现类。从JDK1.6开始,Java提供了一个Deque接口,并为该接口提供了一个ArrayDeque实现类。在无须保证线程安全的情况之下,程序中完全可以使用ArrayDeque来代替Stack类。Deque接口代表双端队列的数据结构。双端队列已经不再是简单的队列,它既具有队列的性质(FIFO),也具有栈的性质(FILO)。
3、1 Vector与ArrayList区别
Vector和ArrayList这两个集合类的本质并没有太大的却别,它们都实现了List接口,而且底层都是基于Java数组来存储集合元素的。从序列化机制的角度来看,ArrayList的实现比Vector的实现更安全。除此之外,Vector其实就是ArrayList的线程安全版本,ArrayList和Vector绝大部分的方法实现都是相同的,只是Vector的方法增加了synchronized进行修饰。除此之外,Vector是一个非常古老的集合,从JDK1.0就开始存在了,那时候它已经包含了大量从操作集合元素的方法,但是这些方法都具有方法名冗长、难于记忆的特点。随着JDK1.2增加了List接口之后,Vector改为实现了List接口,因此Vector将原有的方法进行了包装,包装成了遵循List接口规范的新方法。
由于Vector包含的方法比ArrayList更多,而且ArrayList的序列化实现比Vector的序列化实现更安全,因此Vector基本上已经被ArrayList所代替。Vector唯一的好处就是线程安全。
提示:即使需要在多线程的环境下使用List集合,而且需要保证List集合的线程安全,则应该考虑将ArrayList包装成线程安全的集合类。Java提供了一个Collections工具类,通过该工具类的synchronizedList方法即可将一个普通的ArrayList包装成一个线程安全的ArrayList。
3、2 ArrayList与LinkedList区别
List代表了一种线性表的数据结构,ArrayList则是一种顺序存储的线性表,底层是采用数组来保存每一个集合元素,LinkedList则是一种链式存储的线性表,其本质上就是一个双向链表,但它不仅实现了List接口,还实现了Deque接口。也就是说,LinkedList既可以当成双向链表使用,也可以当成队列使用,还可以当成栈来使用(Deque代表双端队列,既具有队列的特征,也具有栈的特征)。
ArrayList底层采用一个数组来保存所有的集合元素,因此在插入元素时要完成下面两件事情。
保证底层封装的数组长度大于集合元素的个数。
将插入位置之后的所有数组元素整体向后移动一个位置。
反过来,当删除ArrayList集合中指定位置的元素时,程序也要进行整体移动,而且还需要将被删除索引的地方的数组元素赋为null。因此,对于ArrayList集合来说,当程序向其中添加、删除元素时,ArrayList底层都要对数组进行整体的移动,所以性能非常差。但如果程序调用get(int index)方法来取出ArrayList集合中的元素时,性能和数组一样都非常的快。
LinkedList本质上就是一个双向链表,因此它在添加集合元素时,只要对链表进行如图所示的操作即可添加一个新的节点,因此可以非常方便地在指定节点之前插入新节点。如果只是单纯地添加某个节点,那么LinkedList的性能会非常的好;但如果需要向指定索引处添加节点,LinkedList必须先找到指定索引处的节点——这个搜索过程的系统开销并不小。
但是LinkedList取出指定的元素就比较麻烦,必须逐个元素地搜索,直到找到第index个元素为止,因此对于系统的开销也比较大。
3、3 ArrayList与LinkedList性能分析及适用场景
当程序需要以get(int index)方法获取List集合指定索引处的元素时,ArrayList性能大大地由于LinkedList。因为ArrayList底层以数组来保存集合元素,所以调用该方法获取指定索引处的元素时,底层实际上调用elementData[index]来返回元素,因此性能非常好。而LinkedList则必须逐个地搜索。当程序调用add(int index , Object obj)方法向List集合中添加元素时,LinkedList性能高于ArrayList。因为ArrayList必须对底层数组元素进行整体移动。如果添加元素导致集合长度超过了底层数组长度,ArrayList必须创建一个长度为原来长度1.5倍的数组,再由垃圾回收机制回收原有数组,因此系统开销比较大。对于LinkedList而言,它的主要开销集中在entry(int
index)方法,该方法必须逐个地搜索,直到找到index处的元素,然后在该元素之前插入新元素。
当程序调用remove(int index)方法删除index索引出的元素时,ArrayList同样也需要对底层数组进行整体移动,但调用remove(int index)删除集合元素时,ArrayList无须考虑创建新数组,因此执行该方法比ArrayList执行add(int index , Object obj)方法略微快一点。当LinkedList调用remove(int
index)方法删除集合元素时,与调用add(int index , Object obj)开销几乎相同。
当调用add(Object obj)方法向List集合尾端添加一个元素时,大部分时候ArrayList无须对底层数组元素进行整体移动,因此也可以获得很好的性能(甚至比LinkedList的性能更好);但如果添加这个元素导致集合长度超过了底层数组长度,ArrayList必须创建一个长度为原来长度1.5倍的数组,再由垃圾回收机制回收原有数组,这样系统开销就比较大了。但LinkedList调用add(Object
obj)方法添加元素时总可以获得很好的性能。
当程序把LinkedList当成双端队列、栈使用时,LinkedList可以快速定位需要操作的元素,因此LinkedList总是具有更好的性能表现。
总而言之,大部分情况之下,ArrayList的性能总是优于LinkedList,因此大部分情况下都应该优先考虑ArrayList集合。但是如果程序经常需要添加、删除元素,尤其是经常需要调用add(E
e)方法向集合中添加元素,则应该考虑使用LinkedList集合。
相关文章推荐
- 常见Java集合的实现细节(一)
- 常见Java集合实现细节——List集合与Map集合
- 常见java集合的实现细节
- java 集合之实现类ArrayList 和 LinkedList
- 常见Java集合实现细节——Iterator迭代器
- 黑马程序员——java集合中的ArrayList和LinkedList
- Java集合源码学习(7)_List接口的实现_LinkedList
- 深入Java集合学习系列:ArrayList的实现原理
- 深入Java集合学习系列一:ArrayList的实现原理
- 深入Java集合学习系列:ArrayList的实现原理
- Java集合源码学习(6)_List接口的实现_ArrayList_Vector
- 深入Java集合学习系列:ArrayList的实现原理
- 深入Java集合学习系列:ArrayList的实现原理
- 深入Java集合学习系列:ArrayList的实现原理
- Java集合学习:ArrayList的实现原理
- 深入Java集合学习系列:ArrayList的实现原理
- 【疯狂Java_突破程序员基本功的16课】charpt3 常见Java集合的实现机制
- 深入Java集合学习系列:ArrayList的实现原理
- 深入Java集合学习系列:ArrayList的实现原理
- Java集合的实现细节【1】——Set集合和Map集合