[Java learning] java container source code (1)

Source: Internet
Author: User

[Java learning] java container source code (1)
I. Dynamic Array ArrayList

In our developers' eyes, this is a "dynamic array", which can be used to dynamically adjust the size of the array, although the size of the array cannot be changed after the length is defined.
The basic principle for implementing "dynamic" adjustment is to re-create an array of the same size after adjustment according to a specific adjustment policy, and assign the original array value back.
Next we will parse several methods that are different from arrays.

Let's take a look at the main fields in ArrayList (source code analysis ):

// Default initial array size: private static final int DEFAULT_CAPACITY = 10; // empty array size: private static final Object [] EMPTY_ELEMENTDATA ={}; // array of data storage, the subject is its private transient Object [] elementData; // The number of array elements (not necessarily equal to the length of the array) private int size;

Add elements (source code profiling ):

Public boolean add (E e) {// determine whether an array needs to be scaled out. You need to scale out (the key method for dynamically adjusting the array size) ensureCapacityInternal (size + 1 ); // array element assignment, number of array elements + 1 elementData [size ++] = e; return true;} public void add (int index, E element) {// check whether the array is out of bounds rangeCheckForAdd (index); // determine whether the array needs to be resized without resizing (the key method for dynamically adjusting the array size) ensureCapacityInternal (size + 1 ); // The index and index elements move backward to the System. arraycopy (elementData, index, elementData, index + 1, size-index); // The value of elementData [index] = element is assigned to the index position; // array element + 1 size ++ ;}

Delete the element. Note that the array size is not reduced, but the size value is modified (source code analysis ):

Public E remove (int index) {// array out-of-bounds check, will throw an exception. rangeCheck (index); // record the number of modifications, modCount ++ will be used in the iterator; // find the data to be deleted E oldValue = elementData (index); // The number of elements to be moved int numMoved = size-index-1; if (numMoved> 0) // copy the array and move the element System. arraycopy (elementData, index + 1, elementData, index, numMoved); // remove the reference to facilitate GC to reclaim elementData [-- size] = null; return oldValue ;} public boolean remove (Object o) {if (o = null ){// Traverse the array, find the first element with a null value, and then delete for (int index = 0; index <size; index ++) if (elementData [index] = null) {// quickly delete fastRemove (index); return true ;}} else {// The same as traversing the array and searching for (int index = 0; index <size; index ++) if (o. equals (elementData [index]) {// locate and delete fastRemove (index); return true ;}// return false is not found ;} // similar to E remove (int index. // I don't understand here. remove (int index) and fastRemove (int index) can reuse code. Why not reuse code? Private void fastRemove (int index) {modCount ++; int numMoved = size-index-1; if (numMoved> 0) System. arraycopy (elementData, index + 1, elementData, index, numMoved); // set null so that GC can reclaim elementData [-- size] = null ;}

Let's take a look at the most important array resizing method (source code analysis ):

Private void ensureCapacityInternal (int minCapacity) {// determines whether the array is an empty array if (elementData = EMPTY_ELEMENTDATA) {minCapacity = Math. max (DEFAULT_CAPACITY, minCapacity);} ensureExplicitCapacity (minCapacity);} private void capacity (int minCapacity) {// number of modifications + 1 modCount ++; // determine whether resizing is required: compare the array size and the size to be resized if (minCapacity-elementData. length> 0) grow (minCapacity);} // increase the capacity to start private void grow (int minCapacity) {int oldCapacity = elementData. length; // x1.5 times int newCapacity = oldCapacity + (oldCapacity> 1); if (newCapacity-minCapacity <0) // the resizing size is too small to newCapacity = minCapacity; if (newCapacity-MAX_ARRAY_SIZE> 0) // the size of the expansion will not exceed the maximum size Integer. MAX_VALUE-8 newCapacity = hugeCapacity (minCapacity); // array copy elementData = Arrays. copyOf (elementData, newCapacity );}

ArrayList is called "the principle of dynamic array", which is roughly like a comment in source code parsing. There are other array operation methods in it. I will not talk about it here, but the idea is similar. The Source Code prevails.

Ii. Linked List queue listing

(Bidirectional) linked list + Queue (Deque ). I used to think that the queue list is just a linked list. I didn't expect it to be used as a queue.

Look at the Node Code and you will know that it is a two-way node (source code ):

Private static class Node
  
   
{E item; Node
   
    
Next; // Node of the successor Node
    
     
Prev; // Node (Node
     
      
Prev, E element, Node
      
        Next) {this. item = element; this. next = next; this. prev = prev ;}}
      
     
    
   
  

Several important fields (source code parsing ):

// Transient: Not serialized // number of nodes transient int size = 0; // The first Node transient Node
  
   
First; // The Last transient Node
   
    
Last;
   
  

A simple look at the linked list Code (source code parsing ):

// Add node public void add (int index, E element) {// check whether the index is out of the checkPositionIndex (index); if (index = size) // Add the last linkLast (element); else // Add it to the front of the original index node linkBefore (element, node (index ));} // Delete the public E remove (int index) node {// check whether the index is out of bounds checkElementIndex (index); // remove the node link return unlink (node (index ));} // search for the public E get (int index) node {// check whether the checkElementIndex (index) is out of bounds. // start searching for return node (index ). item;} // This method is used to find the Node
  
   
Node (int index) {// half-lookup ~, The advantage of the two-way linked list is that if (index <(size> 1) {// you can find the First Half of the Node from the front.
   
    
X = first; for (int I = 0; I <index; I ++) x = x. next; return x;} else {// find the last half Node from the back
    
     
X = last; for (int I = size-1; I> index; I --) x = x. prev; return x ;}}
    
   
  

A simple look at the queue code (source code parsing ):

// Enter the public boolean offer (E e) {return add (e);} // The public boolean add (E e) {// connect to the last node linkLast (e); // personally think that this return true is unnecessary, and there is no return value void, so that if the team fails to join, linkLast will throw an exception. Since an exception is thrown, it will not return false, so there is no need to return true. Return true;} // "gently" retrieves the Header element of the team. If the team is empty, no exception is thrown. Only null public E peek () {final Node is returned.
  
   
F = first; return (f = null )? Null: f. item;} // "rudely" gets the Header element of the team. If the team is empty, a NoSuchElementException exception is thrown. public E element () {return getFirst ();} // "gently" leaves the team, if the team is empty, no exception is thrown. Only null public E poll () {final Node is returned.
   
    
F = first; return (f = null )? Null: unlinkFirst (f);} // A NoSuchElementException exception is thrown when the team is empty. public E remove () {return removeFirst ();}
   
  
3. Secure dynamic array Vector

Lock ArrayList (thread security ). The method implementation is similar to that of ArrayList. The difference is that synchronized is applied to unsafe threads.
Generally, ArrayList is used instead of Vector, unless it is used in a multi-threaded environment (as a last resort.

Iv. Stack

Stack, the parent class is Vector, so you know (locking dynamic array ). Since the parent class is "secure", the stack as a subclass should also be "secure" (locked !), So the stack is not very fast ~.
Stack specifies that the last element of the array is the top element of the Stack.

Stack (source code parsing ):

// No lock? The addElement of the parent class Vector has been locked, so no extra lock is required. Public E push (E item) {// Add the element to the end of the last element of the array addElement (item); // return the element pushed to the stack return item ;}

Output stack (source code parsing ):

// Public synchronized E pop () {E obj; // number of elements in the stack int len = size (); // obtain the top element obj = peek (); // remove the last element (that is, remove the top element of the stack) removeElementAt (len-1); // return the removed top element return obj ;} // get the top element of the stack public synchronized E peek () {int len = size (); if (len = 0) // empty stack exception throw new EmptyStackException (); // return elementAt (len-1 );}

Stack element search, from the top of the stack (the last array element) to the bottom of the stack (the first array element) (source code analysis ):

Public synchronized int search (Object o) {// find the last compliant element int I = lastIndexOf (o); if (I> = 0) {// return size ()-I;} // return-1;} not found ;}
5. PriorityQueue

PriorityQueue implements priority queue (default minimum heap ).
Difficulties in implementing priority queue: You need to adjust the heap.
The methods for adjusting the heap are: Upper filter and lower filter.

Several important fields (source code parsing ):

// Default initialization container size private static final int DEFAULT_INITIAL_CAPACITY = 11; // element array private transient Object [] queue; // number of elements private int size = 0; // The comparator (Extensible). It can be null. If it is null, E must implement the Comparable interface. Private final Comparator
  Comparator; // number of changes private transient int modCount = 0;

Add element (join) (source code parsing ):

Public boolean add (E e) {return offer (e);} public boolean offer (E e) {if (e = null) throw new NullPointerException (); // number of modifications + 1 modCount ++; int I = size; // determines whether the array should be expanded if (I> = queue. length) // resize the array grow (I + 1); // Add 1 size = I + 1 to the array element; if (I = 0) // The first queue element queue [0] = e; else // because an element is added, you need to adjust the heap (bottom to top): siftUp (I, e ); return true ;}

Let's take a look at the method for adjusting the heap (source code parsing ):

Filtering (source code parsing ):

// Select the private void siftUp (int k, E x) {if (comparator! = Null) // preferentially select siftUpUsingComparator (k, x) with a comparator; else // siftUpComparable (k, x) for the Comparable object );} // The private void siftUpComparable (int k, E x) of the Comparable object can be forcibly converted to a Comparable object.
  Key = (Comparable
  ) X; while (k> 0) {// k is the subnode subscript in the array, (k-1) /2 You can find the parent node subscript int parent = (k-1)> 1; // obtain the parent node Object e = queue [parent]; // if the key is greater than or equal to the parent node if (key. compareTo (E) e)> = 0) break; // The key is smaller than the parent node // the exchange value between the parent node and the child node queue [k] = e; // The location where k runs to the parent node k = parent;} // assign a value to the proper location queue [k] = key;} // use the filter of the comparator (resolution is the same as that of siftUpComparable) private void siftUpUsingComparator (int k, E x) {while (k> 0) {int parent = (k-1) >>> 1; Object e = queue [parent]; if (comparator. compare (x, (E) e)> = 0) break; queue [k] = e; k = parent;} queue [k] = x ;}

Filter (source code parsing ):

// Downstream filtering (same as filtering twice) private void siftDown (int k, E x) {if (comparator! = Null) siftDownUsingComparator (k, x); else siftDownComparable (k, x);} // private void siftDownComparable (int k, E x) {Comparable
  Key = (Comparable
  ) X; // calculate the number of non-leaf nodes int half = size> 1; while (k ) C ). compareTo (E) queue [right])> 0) // select the right child as the object of comparison with the parent node c = queue [child = right]; // compare if (key. compareTo (E) c) <= 0) // if the parent node is smaller than or equal to the child node, locate the position break to be adjusted; // assign the value of the child node to the parent node queue [k] = c; // change the child node to the next cycle to compare k = child;} // locate the adjusted position, assign a value to queue [k] = key;} // use the lower filter of the comparator (same as siftDownComparable) private void siftDownUsingComparator (int k, E x) {int half = size >>> 1; while (k 

Summary: after reading the classes in the java container package, the understanding of the data structure is further deepened. It is true that the source code is "good stuff ". The classes mentioned here are not comprehensive, and they are not complete yet!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.