Collection category

Two, Map collection category

HashTable 

  Thread-safe, default length is 11, the expansion of 2 * length + 1, and in the case of default length, the first expansion length 23, 47 of the second expansion length.

  Source Interpretation slightly.

 


 HashMap 

  Non-thread-safe, the default length of 16, expansion is 2 times the current length of the array.

  Specific expansion can refer to my other article: https://www.cnblogs.com/yanzige/p/8392142.html

 


 ConcurrentHashMap 

  Thread-safe, the default length of 16, expansion is 2 times the current length of the array.

  JDK8 Source Interpretation: https://blog.csdn.net/ddxd0406/article/details/81389583

 


 Laidakedःashanap 

  Non thread-safe, parent a HashMap, so the default length of 16, the load primers 0.75, 2-fold expansion of the original length.

  Because the parent a HashMap, so many methods and parent classes, the bottom layer is a maintains an array, each location has an Entry list, it should be noted that, Entry each object position (as LinkedHashMap in the of Entry Entry to the HashMap succession, but two new Entry object in succession during each Entry object for recording and next Entry object) is saved before and after the insertion of other objects Entry position (this position may not be Entry subject under the same array), in this way, different data can be strung Entry list a whole list, which is a doubly linked list.

  Note: The following Entry JDK8 source is used, so that the LinkedHashMap Entry Node object HashMap in succession, in fact, can be directly understood JDK8 Node objects in object as the JDK7 Entry (both of exactly the same structure, it is made final int hash; final K key; V value; Node <K, V> next; composed, just name it is called is different), so the text collectively Entry.

Copy the code
  /**
     * HashMap.Node subclass for normal LinkedHashMap entries.
     */
    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }
Copy the code

 

  Entry can be seen from the above codes, LinkedHashMap HashMap and the addition of Entry Entry same int hash, K key, V value, Node <K, V> next four objects (the list used for recording the subject under one array information), but also more Entry <K, V> before, after Entry before and after the two, used to record data before and after the new Entry (when new data, may add hash conflicts on the same chain, may in new data on the position of the other chain or other location of the array). In this way maintains a two-way linked list.

  HashMap relative, because the LinkedHashMap array subscript of each chain link up position, maintains a two-way linked list, it can be recorded inserted LinkedHashMap sequential data, and HashMap insertion order can not be recorded.

 to sum up:

  1, HashMap and LinkedHashMap not thread-safe.

  2, HashTable are thread-safe, but the lock is on the way to means-plus-synchronized, and the whole object lock HashTable need to operate, can be understood as a full table lock, there is only one thread to access any HashTable objects, other threads need to wait. It is complicated by inefficient.

  3, HashMap and ConcurrentHashMap inherited AbstractMap class, HashTable is inherited from the Dictionary class, and LinkedHashMap inherited from HashMap class, four of them who have achieved the Map interface.

  . 4, LinkedHashMap inherited HashMap, the underlying principle and basic operation and HashMap as, but maintains a plurality of bidirectional linked list, such that the inserted sequence LinkedHashMap data can be recorded.

  5, ConcurrentHashMap default length is also 16, and also the expansion mode as HashMap.

    . 1) used in JDK7 ConcurrentHashMap locking segment, as compared to the full table lock HashTable, ConcurrentHashMap multiple threads access the object, if not the same segment of data, multi-threading can operate simultaneously.

    2) ConcurrentHashMap use of atomic operations (CAS) and the synchronized code block in JDK8, so that locking granularity finer, better concurrency.

 

Three, List collection category

ArrayList 

  Non-thread safe, except for the size specified default length is 10, the expansion is 1.5 times the previous length. If the object is first created using the constructor with no arguments, when put in the empty array (0) to the default length of 10 expansion.

  1, ArrayList three constructors

  0) First class variables defined See

Copy the code
    / ** 
     * initial capacity size 
     * / 
    Private Final static int DEFAULT_CAPACITY = 10; 

    / * 
     * initialize an array 
     * / 
    Private static Final Object [] = {} EMPTY_ELEMENTDATA; 

    / ** 
     * the ArrayList object underlying data objects stored as an array of Object 
     * / 
    Private transient Object [] elementData of; 

    / ** 
     * size of the amount of data stored the ArrayList 
     * / 
    Private int size;
Copy the code

  

  1) No argument constructor

Copy the code
    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    } 
Copy the code

  When no-argument constructor to create an object, did not specify the size of the container, the container size is specified in the first add () when

  public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

  In (size + 1) ensureCapacityInternal method, the data is placed in time, checks if the array (whether the object is to initialize the ArrayList array), if the object is then initialized, then the current default length and the length of a comparator 10, maximum value, then perform ensureExplicitCapacity (minCapacity)

Copy the code
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
Copy the code

  Entering ensureExplicitCapacity () compares the current size and elementData.length size, if the current data is greater than the length of the ArrayList, expansion is performed. The first expansion came in certainly grow (minCapacity), because the current value of 0 elementData.length

Copy the code
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
Copy the code

  The following is the code expansion, the expansion of the new default length of the array to 1.5 times the original length of the array, the following code uses the original length original length plus the right by 1 bit (>> 1), i.e. the new length = (1 + 0.5) Original length and copy the original array data to the new array. If new first add () when data, oldCapacity is 0, i.e. the newCapacity = minCapacity newCapacity = 10.

Copy the code
    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);
    }
Copy the code

  In the above expansion process, and length checking, determining whether the maximum expansion of the length of the operating length of the array and the largest integer (int) length positive integer, and the 31 th -12

Copy the code
    /**
     * 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;

    /**
     * 最大整型正整数 2的31次方-1,16进制为0x7fffffff; 
     */
    public static final int   MAX_VALUE = 0x7fffffff; 
Copy the code
Copy the code
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
Copy the code

  

  2) specified capacity constructor

Copy the code
    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }
Copy the code

 

  3) Specify the upper limit set constructors

Copy the code
    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
Copy the code

to sum up:

  1) ArrayList Object is an underlying array when the object is initialized, if the constructor with no arguments, a default size is 10, set the initial size of the first time data is added.

  2) ArrayList expansion is to copy the original data array to 1.5 times before the new array, but the first, each expansion capacity have become

  3) ArrayList underlayer is an array, so continuous data storage, they support the use of subscripts to access elements, the index data faster speed .

 


 Vector

  Thread-safe, substantially all of such methods are synchronized using a modified (e.g.: public synchronized boolean isEmpty () {return elementCount == 0;}), it is thread safe. And ArrayList as inherited AbstractList <E> class constructor with no arguments default capacity size of 10, Vector constructor has four, a non-argument constructor, a specific configuration of capacity size, a specified capacity size over storage after the specified size expansion builder, and a specified upper limit set constructors.

  1, the first three are the constructor call the constructor bottom two parameters: the size and capacity of a given specified size exceeds the amount of storage expansion constructor

Copy the code
    /**
     * Constructs an empty vector with the specified initial capacity and
     * capacity increment.
     *
     * @param   initialCapacity     the initial capacity of the vector
     * @param   capacityIncrement   the amount by which the capacity is
     *                              increased when the vector overflows
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

    /**
     * Constructs an empty vector with the specified initial capacity and
     * with its capacity increment equal to zero.
     *
     * @param   initialCapacity   the initial capacity of the vector
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    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);
    }
Copy the code

  2, the upper limit of the specified set constructors

Copy the code
    /**
     * Constructs a vector containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this
     *       vector
     * @throws NullPointerException if the specified collection is null
     * @since   1.2
     */
    public Vector(Collection<? extends E> c) {
        elementData = c.toArray();
        elementCount = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }
Copy the code

  3, at the time of expansion, if no expansion of specified size, i.e., without using the above constructors public Vector (int initialCapacity, int capacityIncrement) initialize the object, then the time of expansion is a direct expansion of 2 times the original

Copy the code
    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);
    }
Copy the code

 


 LinkedList 

  Non-thread-safe, LinkedList underlying maintains a doubly linked list, the list has a forward node Node <E> first and a post <E> last node to the Node. Each time new data add (), when a new node is added after the last node last, and the assignment of new node just added to the last. If it is the first time the new, then the new node is both a first node, but also the last node.

  NOTE: Node <E> node data which will be stored before a node, the node data and its own value. After each new node, the last node before the node data on a new node was added, the new node of a node was empty, while the current data will be stored on the new node in a node the lower node information. This entire string to a linked list in addition to the first and last nodes, each node contains information on a node and the next node. All data before because the previous node and data node in a node Node there, so just open any Node node data forward to see the node, you can view all of the data back after the node. If the node is the head, the back can see the list of all the data, if the node is in the tail, you can view all data in the forward list.

  FIG tail in the following list, a node below this node is empty, you can see all the data forward:

 

  1, add () method adds data

  add () method using add data linkLast (), the last data stored in the list information of the current node before a Node node, the next node of the current node Node is empty, and replace the current Node last node. Add the code flow can be seen from it, and not treated LinkedList repetitive data added at the time, it is stored in the LinkedList duplicate data. After the addition was completed, the final length of the linked list data size size plus one, then the number of operations modCount data plus 1.

    public boolean add(E e) {
        linkLast(e);
        return true;
    }
 
Copy the code
    /**
     * Links e as last element.
     */
    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++;
    }
Copy the code

 

  2, let's look at some remove () method

Copy the code
  public E remove() {
        return removeFirst();
    }

    public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    } 
Copy the code

  delete remove method by calling unlinkFirst (f) and unlinkLast (l), remove either the head or the tail, the element or intermediate position, the links, are required to connect the front and rear.

Copy the code
    / ** 
     * Delete first header data, the header data to the next data for the new first fist node, then the first set of nodes prev The node is empty, 
   * then the original data is deleted firt head node, then the original data blanking next header node. Finally, the data size minus the length of a list, the number of operations plus a modCount * / Private E unlinkFirst (the Node <E> F) { // First Assert == F F = null &&;! Final E = Element f.item; Final Next = f.next the Node <E>; f.item = null; f.next = null; // the GC Help First = Next; IF (Next == null) Last = null; the else next.prev = null; size- -; ModCount ++; return Element; } / ** * Remove tail data Last, the first take out prev tail node data, and the extracted node is set as a Last, while the next set therein is set to null,
   * and tail data and the node the prev blank. Finally, the chain length data size and a reduced number of operations plus a modCount * / Private E unlinkLast (the Node <E> L) { // Last Assert && L = L == null;! Final E = Element l.item; Final the Node <E> PREV = l.prev; l.item = null; l.prev = null; // Help the GC Last = PREV; IF (PREV == null) First = null; the else prev.next = null; size-- ; ModCount ++; return Element; } / ** * Remove the intermediate node data, extracted next node and prev node data of the node and the previous node prev is next set to delete the data next, the next data set prev node data after a node is about to delete data next data,
   * then all data will be deleted blanking data, and finally the chain length data size and a reduced number of operations plus a modCount * / E the unlink (the Node <E> X) { // Assert X! = null ; Final E = Element x.item; Final the Node <E> = Next x.next; Final the Node <E> PREV = x.prev; IF (PREV == null) { First = Next; } the else { prev.next = Next; x.prev = null; } IF (Next == null) { Last PREV =; } the else { next.prev = PREV; x.next = null; } x.item = null; size--; modCount++; return element; }
Copy the code

 


 CopyOnWriteArrayList 

  Thread safety, and concurrent package under contract, used to read and write ReentrantLock locks to ensure data security, only one thread at a time for writing, but you can have multiple concurrent threads read data, while guaranteed by the volatile keyword after reading the data when visibility, and modified each time data in main memory, working memory, the data will be read with the new as the latest data, to ensure the security thread to read the data. CopyOnWriteArrayList no initial capacity size.

By maintaining the visibility of the underlying array is to store data, the array using that volatile, guaranteed data

private transient volatile Object[] array;

  CopyOnWriteArrayList when reading and writing using ReentrantLock to ensure thread safety, why do not absolutely say CopyOnWriteArrayList it thread safe? The reason is that CopyOnWriteArrayList that in order to ensure the efficiency of read and write, write and modify the time data can be read, it will have a thread-safe (error) problem when the data is deleted when data is deleted during the same time in reading take the data, delete a snap, and then read the data occurs, the error will be: array index out of bounds. You can refer to: https://www.jianshu.com/p/fc0ee3aaf2df

Related Reading For more CopyOnWriteArrayList can be traced: https://www.cnblogs.com/myseries/p/10877420.html

 

Summary on ArrayList, Vector, LinkedList and CopyOnWriteArrayList comparison:

  . 1, the underlying principle ArrayList and Vector, are used Object data are inherited AbstractList <E> class is not specified, then the default initial capacity are 10, when the expansion ArrayList to 1.5 times, and the expansion of the original Vector 2 times. Second ArrayList class is not thread-safe, but Vector is thread-safe. Because Vector use synchronize to ensure thread safety, efficiency and so on ArrayList compared to low.

  2, CopyOnWriteArrayList underlayer also be an array, but no initial capacity. CopyOnWriteArrayList security thread, and thread-safe Vector comparison, using as CopyOnWriteArrayList ReentrantLock lock yoke specified code block, to meet the demand for multi-threaded read, and can read data in the write process, as compared to the Vector class synchronize way to lock the whole process more concurrent efficiency.

  3, LinkedList bottom using a doubly linked list, and the above two principles are not the same, is not thread-safe. Because the underlying LinkedList is a linked list, so LinkedList is high time to add and delete data in efficiency, but at the time of need, traversing query, so efficient is low. Instead, ArrayList and Vector underlying the use of arrays, memory addresses are continuous, so when the query is very efficient, but in the design of new and deleted expansion (copy of the array), so the efficiency is lower compared to LinkedList.

 

Guess you like

Origin www.cnblogs.com/kakaisgood/p/12613672.html