目录
ArrayList
特点:继承于AbstractList,它还实现了RandomAccess, Cloneable, java.io.Serializable等接口。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
内容是有序的(插入顺序)并且是允许重复且允许为NULL,集合可 使用clone方法(Cloneable),可以进行序列化操作(Serializable),可以被随机访问(RandomAccess),可以使用迭代器遍历
使用场景:适合于数据不需要做大量的随机插入、删除操作的场景;比较适合数据的随机访问。因为ArrayList的 底层数据结构是数组,进行随机插入、删除操作的时候会涉及到大量的数据元素的移动,这会使效率变低。
源码实现:底层数据结构是数组;初始容量为空,当插入第一个元素时,初始容量为10,当容量满了进行1.5倍扩容;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
线程是否安全:线程不安全
LinkedList
特点:继承于AbstractSequentialList,还实现了RandomAccess,Cloneable, java.io.Serializable等接口.
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
内容是有序的(插入顺序)并且是允许重复且允许为NULL,并且可以使用迭代器来遍历
使用场景:不适合数据需要大量的随机访问的操作;适合于数据的随机插入、删除或修改操作。因为LinkedList的底层数据结构是双向链表,进行数据的随机访问的时候,需要从头或者从尾部遍历,这会使效率降低。
源码实现:双向链表
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
线程是否安全:线程不安全
Vector
特点:继承于AbstractList,它还实现了List, RandomAccess, Cloneable, java.io.Serializable等接口。
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- 内容是有序的(插入顺序)并且是允许重复且允许为NULL,集合可使用clone方法(Cloneable)
- 可以进行序列化操作(Serializable)
- 可以被随机访问(RandomAccess)
- 可以使用迭代器遍历
使用场景:当有线程安全的需求的时候比较适合使用vector,因为vector是线程安全的集合;而当没有线程安全的需求的时候适合使用ArrayList(效率更高,因为vector的加锁操作很耗时。)
源码实现:底层数据结构是数组;初始容量为10,当容量满了之后有两种选择:
- 当增长因子(capacityIncrement )小于0的时候直接进行二倍扩容
- 当增长因子(capacityIncrement )大于0的时候,扩大增长因子个大小,与ArrayList相比较,vector的扩容方法更加的合理。因为在数据基数较大时,比如有1000个元素,这时我只需要再插入1个元素即可满足要求,使用ArrayList的话,就会自动扩容到1500个空间,那么499个空间将被浪费;如果用Vector,我可以设置增长因子(capacityIncrement )为2,那么我就只有1个空间被浪费。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
线程是否安全:线程安全,vector中的所有方法都加了synchronized锁,所以vector是线程安全的集合。
比如capacity方法:
/**
* Returns the current capacity of this vector.
*
* @return the current capacity (the length of its internal
* data array, kept in the field {@code elementData}
* of this vector)
*/
public synchronized int capacity() {
return elementData.length;
}
Stack
特点:继承于vector
public
class Stack<E> extends Vector<E>
stack中方法的实现大多是沿用了vector中的方法
使用场景:具有栈特点的数据处理方法,符合先进后出的要求。
数组与集合的区别
数组:当你创建了一个数组的时候,那么这个数组的容量就已经确定了,无法进行扩容等操作,所以数组比较适合事先就已经知道所要存储的数据元素的数量的情况下使用。与集合相比,数组少了扩容、删除等相关方法,故而数组的效率也更高。
集合:集合在存储数据元素的同时,还添加了许多对数据进行操作的方法,如添加、删除、修改等。像ArrayList这样的底层数据结构是数组的集合,还添加了扩容方法,所以集合有着更加广泛的使用场景。