[Series] collection - simple analysis of interface Collection List

A, List Introduction

List data structure is a sequence, when the stored content directly open a continuous space in the memory, then the address space corresponding to the index.

The following is a collection of simple architecture diagram List

The inheritance graph, you can know, ArrayList, LinkedList, Vector, Stack List of all four implementation class.

  • AbstractCollection is an abstract class, it is the only class Collection interface implementation. AbstractCollection mainly achieved toArray (), toArray (T [] a), remove () method and the like.
  • AbstractList is an abstract class that inherits from AbstractCollection. List interface implemented in addition AbstractList size (), get function (int location) than such specific iterator ListIterator.
  • AbstractSequentialList is an abstract class that inherits from AbstractList. AbstractSequentialList achieve a "linked list, according to all the functions of the operating chain index value index."
  • ArrayList is a dynamic array, which is implemented by arrays. High efficiency random access, random insertion, deletion random low efficiency.
  • LinkedList is a doubly linked list. It can also be used as a stack, queue, or deque operate. LinkedList random access efficiency is low, but the random insertion, deletion random high efficiency.
  • Vector is also a dynamic array and ArrayList, just as implemented by the array. But ArrayList is non-thread-safe, but Vector is thread-safe.
  • Stack is the stack, it is inherited from Vector. Its characteristics are: last-out (FILO, First In Last Out).

A description of each class that implements methods to analyze!

二、ArrayList

List ArrayList implements the interface, but also the order of the container, i.e. the data elements stored in the same order into them, permitted in null elements, is achieved by the underlying array.
In addition to the class synchronization is not implemented, the remaining roughly the same with Vector.

After Java1.5, the collection also offers a generic, generic just syntactic sugar provided by the compiler, easy programming, the program will not have substantial impact. Because all classes are inherited to the default Object, so the array is an array of Object here, to be able to receive any type of object.

Common methods

2.1, get method

get () method is also very simple, first determine whether the incoming index out of bounds, then obtain the specified element.

public E get(int index) {
        rangeCheck(index);
        return elementData(index);
}

/**
 * 检查传入的index是否越界
 */
private void rangeCheck(int index) {
        if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

2.2, set method

set () method is also very simple, direct assignment to the specified position in the array.

public E set(int index, E element) {
        rangeCheck(index);
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
}

2.3, add method

ArrayList additive element has two methods, one is to add (E e), and the other is add (int index, E e) .
These two methods are adding a new element to the vessel may occur capacity (capacity) shortage, so before adding elements need to be checking the remaining space, automatic expansion if necessary. The final expansion operation by Grow () method is completed.

grow method implementation

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//原来的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);
}

There is another element to add the addAll () method, the addAll () method of a plurality of elements can be added, depending on the location has two methods, one is added to the end of addAll (Collection <? Extends E> c) method, is a specified position start inserting addAll (int index, Collection <? extends E> c) method.

Different points: addAll () time complexity not only with the insertion of elements related to how much, is also associated with the insertion location, time complexity is linear growth!

2.4, remove method

remove () method has two versions, one is remove (int index) Removes the specified element position; the other is remove (Object o), to remove by the first element satisfies o.equals (elementData [index]).

The following elements need to delete point moves forward one position. Note that in order to allow GC to function, must be explicitly assigned to the last position of a null value.

  • remove (int index) method
public E remove(int index) {
        rangeCheck(index);
        modCount++;
        E oldValue = elementData(index);
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; //赋null值,方便GC回收
        return oldValue;
}
  • remove (Object o) method
public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
}

Three, LinkedList

In the previous article, we know that while LinkedList implements List interface and Deque interfaces, which means that both can be seen as a sequence container, but also can be seen as a queue (Queue), at the same time can be seen as a stack (Stack) .

LinkedList bottom by a doubly linked list to achieve, by firstand lastrefers to the first and last elements point to the list, note that there is no so-called dummy (if a parameter is not used in a subroutine or function, it is called dumb yuan), when the list is empty firstand lastpoint to null.

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;
    
    ......
}
/**
 * 内部类Node
 */
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;
    }
}

Common methods

3.1, get method

get () method is also very simple, first determine whether the incoming index out of bounds, then obtain the specified element.

public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
}

/**
 * 检查传入的index是否越界
 */
private void checkElementIndex(int index) {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

3.2, set method

set (int index, E element) method at the specified index of the element modified to a specified value, but also a reference table element corresponding to the first found by the node (int index), and then modify the value of the item in the Node.

public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
}

3.3, add method

Similarly, there are add () method two methods, one is to add (E e), and the other is add (int index, E element).

  • add (E e) method

The method of LinkedList insert elements at the end, because the end of the list last point, spent elements inserted at the end of the time constant, simply to modify several related references.

public boolean add(E e) {
        linkLast(e);
        return true;
}

/**
 * 添加元素
 */
void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            //原来链表为空,这是插入的第一个元素
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
}
  • add (int index, E element) Method

The method is specified in the table at the insertion element, it is necessary to find out where to find linear, and then complete the insertion and modify references.

Specifically divided into two steps, according to a first index to find the location to be inserted; 2. Modify references, complete the insertion operation.

public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            //调用add方法,直接在末尾添加元素
            linkLast(element);
        else
            //根据index找到要插入的位置
            linkBefore(element, node(index));
}

/**
 * 插入位置
 */
void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
}

Also, there is another additive element the addAll () method, the addAll () method of a plurality of elements can be added, depending on the location has two methods, one is added to the end of addAll (Collection <? Extends E> c) Method the other is inserted from the start position designated addAll (int index, Collection <? extends E> c) method.

There is also a for loop to add elements, addAll () time complexity not only with the insertion of elements related to how much, is also associated with the insertion location, time complexity is linear growth!

3.4, remove method

Similarly, the Remove () method has two methods, one is to delete the specified elements remove (int index) at the index, with the other specified elements is to remove the first element is equal to remove (Object o).

Are two deletions, 1. First find the element you want to delete the references; 2. to amend the relevant quote, complete the deletion .

  • remove (int index) method

Use the following table to find the corresponding node, and then delete it

public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
}
  • remove (Object o) method

Equals found by determining the corresponding node, then delete

public boolean remove(Object o) {
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
}

Delete operations are by unlink(Node<E> x)method done. You should consider removing the element is the first or the last time the border situation.

/**
 * 删除一个Node节点方法
 */
E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;
        
        //删除的是第一个元素
        if (prev == null) {
            first = next;
        } else {
            prev.next = next;
            x.prev = null;
        }
        //删除的是最后一个元素
        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
}

Four, Vector

Vector belong to a subclass of class to save, back in the jdk1.0, it already exists such, but the focus after jdk1.2 to emphasize the concept of the collection, so has defined a number of new interfaces, such as ArrayList, LinkedList , but considering that most have become accustomed to using earlier Vector class, so for compatibility, java designer, let Vector implements a multi-List interface, this will leave it down.

In use, the Vector get, set, add, removemethod of implementation, the ArrayList basically the same, the difference is added to the Vector thread synchronization lock on the method synchronized, execution efficiency, will be slower!

4.1, get method

public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
}

4.2, set method

public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
}

4.3, add method

public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
}

4.4, remove method

public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
}

Five, Stack

In Java Stack class represents a last-in first-out (LIFO) stack of objects. Stack is a very common data structure, which uses advanced mode of operation after the typical completed; in real life, pistol magazine of bullets is a typical LIFO structure.

In use, the main methods are push, peek, pop.

5.1, push method

indicates the push method, add elements to the stack

public E push(E item) {
        addElement(item);
        return item;
}

5.2, peek method

peek method represents a view of the top of the stack objects, but does not remove it from the stack

public synchronized E peek() {
        int     len = size();
        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
}

5.3, pop method

pop method, said removing elements, and elements of the method to be removed

  public synchronized E pop() {
        E       obj;
        int     len = size();
        obj = peek();
        removeElementAt(len - 1);
        return obj;
}

About Stack class in Java, there are many voices of doubt, more suitable queue stack structure to achieve, which makes the Stack is not rigorous in design, therefore, under the category of official recommended the use of Deque is to achieve stack!

VI Summary

  • ArrayList (dynamic array structure), fast query (random access or sequential access), deletions slow, but at the end of insertion, almost the same speed and LinkedList!
  • LinkedList (doubly linked list structure), slow queries, additions and deletions fast!
  • Vector (dynamic array structure), are slow compared to ArrayList, ArrayList alternative is substantially not in use. Advantage is thread-safe (functions are synchronized), if you need to use in a multithreaded, concurrent containers are recommended tools to operate, high efficiency!
  • Stack (stack structure) inherited from Vector, the data is in, last out, basically not in use, if you want to achieve stack, ArrayDeque under Deque is recommended to use, more efficient than Stack!

VII reference

1, JDK1.7 & JDK1.8 source
2, CarpenterLee - the Java collection analysis
3, blog Park - Deadwood - Compare ArrayList, LinkedList, Vector, Stack's

Author: fried chicken cola
Source: www.pzblog.cn

Guess you like

Origin www.cnblogs.com/dxflqm/p/11867924.html