ArrayList, LinkedList, Vector, CopyOnWriteArrayList difference and source code analysis

1. ArrayList

ArrayList queue is an array, corresponding to dynamic array . Compared with Java in the array, its capacity can grow dynamically . It inherits AbstractList, implements List, RandomAccess, Cloneable, java.io.Serializable these interfaces. The default size is 10 (from the source can be seen that each expansion capacity of 1.5 times , int newCapacity = oldCapacity + (oldCapacity >> 1);). Operation in the ArrayList is not thread safe! So, it is recommended only to use ArrayList in a single thread , and in multiple threads can select Vector or CopyOnWriteArrayList .

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    ......
    
    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }    
    
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    public ArrayList(Collection<? extends E> c) {
        ......
    }

    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);
        }

    public int size() {
        return size;
    }

       ......
}

1.1 ArrayList expansion

ArrayList default capacity is 10, when inserted into the first element 11 will, when expansion, each expansion increased to 1.5 times, from the code can be int newCapacity = oldCapacity + (oldCapacity >> 1);seen.

2. LinkedList

As ArrayList and LinkedList implement the List interface, but LinkedList is doubly-linked list implementation.

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
       transient int size = 0;

    transient Node<E> first;

    transient Node<E> last;

    public 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;
                }
        }

    ......
}

2.1 The difference between ArrayList and LinkedList

  • Traversal can use ordinary for loop, foreach loop, Iterator interface
  • ArrayList based on an array realization, LinkedList Based doubly linked list
  • ArrayList random access and modification efficiency is relatively high, LinkedList insertion and deletion of more efficient

3. Vector

Vector is thread-safe, there are a lot of synchronized can be seen from the source code. Vector is a dynamic array thread-safe Java earlier provided, synchronized keyword modification almost all the methods of external exposure, so much larger than the read write operation scenarios, Vector will happen a lot of lock contention, leading to performance overhead to the system. For writing it is greater than the reading of a scene .

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    ......
    protected Object[] elementData;
    protected int elementCount;
    protected int capacityIncrement;

    public Vector(int initialCapacity) {
            this(initialCapacity, 0);
    }

    public Vector() {
            this(10);
        }
    
    public synchronized int capacity() {
            return elementData.length;
        }

    public synchronized int size() {
            return elementCount;
        }
    ......
}

The difference between ArrayList and the Vector

 

  • Vector is thread-safe , there are a lot of synchronized source code can be seen, but not ArrayList . So in a single thread, ArrayList Vector higher than performance .
  • ArrayList and Vector underlying continuous memory array are used, sufficient storage space when the capacity is needed, ArrayList default increased to 1.5 times, the default Vector increased to 2 times the original ;
  • Find a designated location data, time arraylist and vector used is the same, they are 0 (1), this time using a Vector and ArrayList can

 

4. CopyOnWriteArrayList

CopyOnWriteArrayList has the following characteristics:

  • Implements List interface;
  • Holds inside a ReentrantLock lock = new ReentrantLock ();
  • A new copy of the array increases, the insertion is completed, modified or removed after the operation assigned to the new array Array ;
  • Additions and deletions are required to obtain a lock, and a lock only, and do not need to get a read lock, supports concurrent . Why additions and deletions to the need to create a new array, after the operation is completed and then assign the original quote? This is to ensure get the time can get to the element, if you modify the original array directly in the process of additions and deletions may cause read operation is performed not obtain data;
  • ReentrantLock ensure internal use thread-safe;

CopyOnWriteArrayList method java.util.concurrent package is provided, which implements the read operation without a lock , the write operation by operating the underlying array new copy is achieved, a separate read and write concurrency strategy

CopyOnWrite Its principle is that any modification operations, such as post-add, set, remove, will copy the original array, modify replace the original array, such a defensive way to achieve alternative thread safe.

So this data structure, is relatively less suitable for reading and writing operations, or modify the cost is still very obvious, suitable for reading much larger than the writing scene .

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
        private static final long serialVersionUID = 8673264195747942595L;
    
    /** The lock protecting all mutators */
    final transient ReentrantLock lock = new ReentrantLock();
    
    /** The array, accessed only via getArray/setArray. */
    private transient volatile Object[] array;

    public boolean add(E e) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                newElements [len] = a;
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }
    
    }

    ......
}

 

Guess you like

Origin www.cnblogs.com/windpoplar/p/11886116.html