LinkedList,ArrayList和Vector
来源:互联网 发布:pinyinime 源码 编辑:程序博客网 时间:2024/05/29 04:16
Collection
我们知道Java中集合分有序和无序两种,其中List有三个实现。
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
List实现
ArrayList、Vector和LinkedList虽然都实现了List接口,还是有一些区别的。
存储
从集合的存储上,ArrayList 和Vector是采取数组体式格式存储数据,而且此数组元素数大于实际存储的数据以便增长和插入元素,因此都允许直接序号索引元素,但是插入数据涉及数组元素移动等内存操纵,所以索引数据快,插入数据慢。源码如下:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ // .... transient Object[] elementData; // non-private to simplify nested class access // ....
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ // .... protected Object[] elementData; /** * The number of valid components in this {@code Vector} object. * Components {@code elementData[0]} through * {@code elementData[elementCount-1]} are the actual items. * * @serial */ protected int elementCount;
对应的LinkedList是采用双向链表实现存储,因此按序号索引数据须要进行向前或向后遍历,然则插入数据时只须要记录本项的前后项即可,所以插入数度较快!源码如下:
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{ transient int size = 0; /** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first; /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node<E> last; /** * Constructs an empty list. */ public LinkedList() { }
同步
Vector因为应用了synchronized方法(即线程安全),所以机能上比ArrayList要稍微差点。
同样的 LinkedList 也没有同步办法,因此当需要多线程访问LinkedList时要实现同步。比如在创建List时创建一个线程安全的List:
List list = Collections.synchronizedList(new LinkedList(...));
null元素
因是有序的,三种实现都是可以存放null。
@Testpublic void testCollection() {ArrayList al = new ArrayList<String>();al.add(null);al.add(null);LinkedList ll = new LinkedList<String>();ll.add(null);ll.add(null);Vector v = new Vector<String>();v.add(null);v.add(null);System.out.println("ArrayList " + al.size());System.out.println("LinkedList " + ll.size());System.out.println("Vector " + al.size());}输出:
ArrayList 2LinkedList 2Vector 2
扩容
提到集合,最容易忽略的就是容量了。这里我用的是JDK 1.8.
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);// 默认容量 为 10 } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;// 扩容次数 // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ private void grow(int minCapacity) {// 真正扩容的地方 // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);// 右移相当于 0.5, 因此扩容至 1.5 倍 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);//将原来数组的值copy新数组中去, 同时ArrayList的引用指向新数组 }
对于Vector扩容,则多了个扩容因子。
首先默认容量还是 10.
public Vector(int initialCapacity) { this(initialCapacity, 0); } /** * Constructs an empty vector so that its internal data array * has size {@code 10} and its standard capacity increment is * zero. */ public Vector() { this(10); }
扩容算法:
public synchronized void ensureCapacity(int minCapacity) {// synchronized 的使用保证了是线程同步。 if (minCapacity > 0) { modCount++; ensureCapacityHelper(minCapacity); } } /** * This implements the unsynchronized semantics of ensureCapacity. * Synchronized methods in this class can internally call this * method for ensuring capacity without incurring the cost of an * extra synchronization. * * @see #ensureCapacity(int) */ private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) {// 真正扩容 // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); // 关键地方 // 扩容因子 >0 时,新容量 = 旧容量 + 扩容因子 // 否则, 新容量 = 旧容量 * 2 if (newCapacity - minCapacity < 0) // 同样, 新容量不够就将数组长度设置为需要的长度. newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
至于LinkedList 是双向链表实现,理论上没有容量限制。当然实际使用时,还是要受内存堆空间的限制。
Collections.synchronizedList
ArrayList
上面提到可用Collections的静态方法synchronizedList()生成一个线程安全的对象,如下:
List<String> alist = Collections.synchronizedList(new ArrayList<String>());但是,该对象内部使用的锁是哪个对象呢?该方法源码如下:
public static <T> List<T> synchronizedList(List<T> list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list)); }查看ArrayList源码知道,其实现了RandomAccess接口。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{// ....}因此synchronizedList()返回的是SynchronizedRandomAccessList的实例。通过下面源码知道该类调用了父类的构造函数, 且其同步方法是基于mutex属性的。
static class SynchronizedRandomAccessList<E> extends SynchronizedList<E> implements RandomAccess { SynchronizedRandomAccessList(List<E> list) { super(list); } SynchronizedRandomAccessList(List<E> list, Object mutex) { super(list, mutex); } public List<E> subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedRandomAccessList<>( list.subList(fromIndex, toIndex), mutex); } } // ... }该属性是定义在其父类SynchronizedCollection中,源码如下:
static class SynchronizedCollection<E> implements Collection<E>, Serializable { // ... final Collection<E> c; // Backing Collection final Object mutex; // Object on which to synchronize SynchronizedCollection(Collection<E> c) { this.c = Objects.requireNonNull(c); mutex = this; } }看到这里我们知道mutex其实就是当前实例。根据继承,子类SynchronizedRandomAccessList的mutex也是SynchronizedRandomAccessList的this对象。因此使用下面返回的对象是线程安全的。
Collections.synchronizedList(new ArrayList<String>());
LinkedList
回看刚才的代码,同样对于 LinkedList 也是线程安全的。
List<String> llist = Collections.synchronizedList(new LinkedList<String>());
0 0
- ArrayList、Vector和LinkedList
- LinkedList、ArrayList和Vector
- LinkedList,ArrayList和Vector
- ArrayList、Vector和LinkedList
- ArrayList、Vector和LinkedList
- ArrayList、LinkedList和Vector
- ArrayList、Vector和LinkedList
- ArrayList、Linkedlist和Vector
- LinkedList,ArrayList和Vector
- vector和arrayList,LinkedList区别
- 比较 ArrayList,LinkedList 和 Vector。
- vector和arrayList,LinkedList区别
- Vector, ArrayList和LinkedList区别
- ArrayList、Vector和LinkedList区别
- ArrayList 、LinkedList和Vector比较
- ArrayList 、LinkedList和Vector比较
- ArrayList, Vector和LinkedList详解
- ArrayList 、LinkedList和Vector比较
- uva 437 DAG上的动态规划
- el表达式和JSTL标签
- 转载:在Vue中通过自定义指令获取元素
- dbms_spm绑定执行计划
- Archive Data DSO Demo 1
- LinkedList,ArrayList和Vector
- java文件流处理jd-gui反编译后文件中每行的注释符
- 查找(1)---顺序查找
- java中gc()与finalize()
- 自定义lucene的同义词分词器
- android L平台增加来电翻转静音菜单、功能
- java.lang.IllegalStateException: Expected BEGIN_OBJECT but was was STRING at line 1 column 1
- 292. Nim Game
- X86汇编 通用寄存器总结