Java list source code analysis, list source code analysis

Source: Internet
Author: User
Tags iterable concurrentmodificationexception

Java list source code analysis, list source code analysis

Three Data Structure linked lists, trees, and graphs. As one of them, the sequence table is the longest used in programming. The List interface is the implementation of sequence tables in java. It has many subinterfaces and implementation classes, which are very convenient to use in programming. But further, we need to understand its implementation and principles, compare it with what we learned in the data structure, and apply it to ordinary programming to compile efficient code.

First, let's take a look at the hierarchical relationship of the list interface, which I drew Based on the jdk class structure:


As you can see, the list interface is derived from the Collection interface. First, you need to understand the Collection interface.

Collection

Collection is the root of the collection framework. It defines the general behavior of set operations, such as adding elements, batch addition, deletion, batch deletion, set size, inclusion, iterator, and so on. Its interface definition is not pasted here. In relation, Collection inherits from the Iterable interface, and there is only one method:

public interface Iterable<T> {     /**     * Returns an {@link Iterator} for the elements in this object.     *     * @return An {@code Iterator} instance.     */    Iterator<T> iterator();}

Here, Iterator is as follows:

public interface Iterator<E> {      public boolean hasNext();        public E next();       public void remove();}

AbstractCollection

AbstractCollection is an abstract Implementation of the Collection interface and implements most of the functions. As shown below, we only need to implement three methods to implement our own Collection:

Collection <String> c =/*** custom implementation example. In the implementation of some methods in AbstractCollection, such as Clear, the * iterator () method is called, in the subclass, implementation of these methods is a typical template mode. **/New AbstractCollection <String> () {/*** Iterator */@ Override public iterator <String> Iterator () {// TODO Auto-generated method stub return null;}/** size */@ Override public int size () {// TODO Auto-generated method stub return 0 ;} /** the abstract implementation throws an exception. We need to implement it ourselves */@ Override public boolean add (String e) {return true ;}};

The following code snippet is taken from AbstractCollection and the iterator method is called. Many similar codes, such as addAll, removeAll, contains, and toArray (), are called. These implementations are only basic implementations, if a subclass has a higher efficiency, it will overwrite it. A typical toArray () of the Arraylist after the visibility ().

public void clear() {    Iterator<E> e = iterator();    while (e.hasNext()) {        e.next();        e.remove();    }    }

List

The List interface represents the linked List in the data structure. It inherits the collection interface and adds some linked List operation methods to it, mainly random access, deletion, searching, and dedicated iterator, as follows:

/** Random get */E get (int index);/*** random set value */E set (int index, E element ); /*** randomly add */void add (int index, E element);/*** randomly remove */E remove (int index ); // Search Operations/*** find */int indexOf (Object o);/*** Search from the back */int lastIndexOf (Object o ); // List Iterators/*** special iteration */ListIterator <E> listIterator ();/*** iterate from a certain position */ListIterator <E> listIterator (int index ); // View/*** subList */List <E> subList (int fromIndex, int toIndex );

AbstractList

This is the abstract implementation of the List interface. Similar to AbstractCollection, it achieves basic functions and delays key methods to implement in sub-classes. A subclass is shown as follows:

List <String> l =/***** example implementation */new AbstractList <String> () {/** random acquisition */@ Override public String get (int index) {return null;}/** size */@ Override public int size () {return 0;}/** throws an exception in the superclass, it indicates that the immutable list is changed to variable */@ Override public String set (int index, String element) {return null ;} /** throw an exception by default */@ Override public void add (int index, String element) {}/*** throw an exception by default */@ Override public String remove (int index) {return null ;}};

ListIterator

A new method is added to the List interface. One of the methods is to return the ListIterator, which extends the iterator and adds the forward Traversal method. The main linked list is ordered.

The implementation is not much said, but it should be noted that the iterator fails. In the list implementation, a field modCount is maintained. when the list is changed, such as add/remove, this value will be changed. When an iterator is constructed, this value will keep a copy in the iterator, and the method in the iterator will check whether the copy is consistent with the modCount in the list, if they are inconsistent, an iterator exception is thrown. Note that the for each syntax in java is an iterator used after compilation.

Example of source code:

Private class Itr implements Iterator <E> {/** this class is an internal class that directly accesses the * Index of element to be returned by subsequent call to next field of abstractList. */int cursor = 0;/*** Index of element returned by most recent call to next or * previous. reset to-1 if this element is deleted by a call * to remove. */int lastRet =-1;/*** note this point */int expectedModCount = modCount;/*** next method of the iterator */public E next () {/** * Check before operation */checkForComodification (); try {E next = get (cursor); lastRet = cursor ++; return next;} catch (IndexOutOfBoundsException e) {checkForComodification (); throw new NoSuchElementException () ;}}/*** check whether the iterator fails. */Final void checkForComodification () {if (modCount! = ExpectedModCount) throw new ConcurrentModificationException ();}}

ArrayList

This is the longest-used data structure in general programming. It is an ordered table based on arrays, but the array can be automatically resized. It directly inherits from abstractList, so it only studies its key implementations and methods.

Array Storage

ArrayList is an array-based storage. By default, the initial size of the structure is 10. We will see that this initial size will affect its performance to a certain extent:

/**     * The array buffer into which the elements of the ArrayList are stored.     * The capacity of the ArrayList is the length of this array buffer.     */private transient Object[] elementData;public ArrayList(int initialCapacity) {    super();        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);    this.elementData = new Object[initialCapacity];    }     /**     * Constructs an empty list with an initial capacity of ten.     */    public ArrayList() {    this(10);    }

Add Method

The List interface has two add overload methods. The first is to add elements at the end of the list, and the second is to add elements at random positions. The method for automatically expanding the data capacity is ensureCapacity (int ), guaranteed size:

/*** This method has been implemented in the parent class, but the arralylist overwrites its implementation and adopts a more efficient implementation */public boolean add (E e) {ensureCapacity (size + 1); // Increments modCount !! ElementData [size ++] = e; return true;}/*** add an element at any position. The corresponding element is moved back to maintain the characteristics of the linked list. * System. arrayCopy is highly efficient. **/Public void add (int index, E element) {if (index> size | index <0) throw new IndexOutOfBoundsException ("Index:" + index + ", Size: "+ size); ensureCapacity (size + 1); // Increments modCount !! System. arraycopy (elementData, index, elementData, index + 1, size-index); elementData [index] = element; size ++;}/*** ensures the size of the list table, if not, scale up. * This method consumes a lot of performance. Therefore, if you can know or estimate the size of AyyayList, you can set an appropriate initial capacity during construction. */Public void ensureCapacity (int minCapacity) {modCount ++; // get the size of the old array int oldCapacity = elementData. length; // compare. if not, expand if (minCapacity> oldCapacity) {Object oldData [] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity <minCapacity) newCapacity = minCapacity; // arraycopy elementData = Arrays with high call efficiency. copyOf (elementData, newCapacity );}}

Vector

The implementation is basically the same as that of ArraaylIst, but the synchronization operation is added to the method. However, you must note that the thread security is relative. For example, one thread performs the add operation and the other thread iterates, exceptions may occur.

In addition, a Stack inherits the Vector and adds Stack-related methods, such as push, and pop.

Shortlist

Compared with ArrayList, sequential tables based on linked lists have a high efficiency in random insertion and deletion because they do not need to expand or move element operations, however, random access is inefficient (random access requires traversal from the first node ).

AbstractSequentialList

AbstractSequentialList inherits from AbstractSequentialList. AbstractSequentialList implements the abstract methods in abstractlist Based on the iterator. it overwrites the method of the returned iterator to the abstract method. Therefore, the key to implementing the consumer list is the iterator, as shown below:

Public abstract class AbstractSequentialList <E> extends actlist <E> {/*** get */public E get (int index) based on the iterator) {try {return listIterator (index ). next ();} catch (NoSuchElementException exc) {throw new IndexOutOfBoundsException ("Index:" + index );}} /*** set */public E set (int index, E element) implemented by the iterator {try {ListIterator <E> e = listIterator (index ); E oldVal = e. next (); e. set (element); return oldVal;} catch (NoSuchElementException exc) {throw new IndexOutOfBoundsException ("Index:" + index );}} /* add */public void add (int index, E element) implemented by the iterator {try {listIterator (index ). add (element);} catch (NoSuchElementException exc) {throw new IndexOutOfBoundsException ("Index:" + index );}} /*** remove Based on iterator **/public E remove (int index) {try {ListIterator <E> e = listIterator (index); E outCast = e. next (); e. remove (); return outCast;} catch (NoSuchElementException exc) {throw new IndexOutOfBoundsException ("Index:" + index);} public Iterator <E> iterator () {return listIterator ();}/*** Returns a list iterator over the elements in this list (in proper * sequence ). **/public abstract ListIterator <E> listIterator (int index );}

Shortlist

In addition to the List interface, the queue List also implements the queue-related interface, which is not mentioned here. According to the listiterator interface, the sorted list is also an ordered table that can be traversed in two directions.

You only need to study the structure and iterator implementation of each linked list node.

The linked list node is a static internal class as follows:

private static class Entry<E> {    E element;    Entry<E> next;    Entry<E> previous;     Entry(E element, Entry<E> next, Entry<E> previous) {        this.element = element;        this.next = next;        this.previous = previous;    }    }

The implementation of its iterator is an internal class. Next we will use its add operation instructions. Others are similar:

Private class ListItr implements ListIterator <E> {private Entry <E> lastReturned = header; private Entry <E> next; private int nextIndex; private int expectedModCount = modCount; /*** use an optimization technique during the construction. The index determines whether to traverse from the front or back. */ListItr (int index) {if (index <0 | index> size) throw new IndexOutOfBoundsException ("Index:" + index + ", Size:" + size ); if (index <(size> 1) {next = header. next; for (nextIndex = 0; nextIndex <index; nextIndex ++) next = next. next;} else {next = header; for (nextIndex = size; nextIndex> index; nextIndex --) next = next. previous;}/** insert in the linked list. When constructing this iterator, index is the insert position. Therefore, insert an element directly. ** addbefor is an Arr. The ayList method is the process of inserting the linked list and changing the pointer. */Public void add (E) {checkForComodification (); lastReturned = header; addBefore (e, next); nextIndex ++; expectedModCount ++;} final void checkForComodification () {if (modCount! = ExpectedModCount) throw new ConcurrentModificationException () ;}}/*** random actsequentiallist method, which is randomly inserted. First, construct the iterator */public void add (int index, E element) {try {listIterator (index ). add (element);} catch (NoSuchElementException exc) {throw new IndexOutOfBoundsException ("Index:" + index );}}

CopyOnWriteArrayList

CopyOnWriteArrayList is a tool class in the java concurrent package. It was introduced in JDK and its content is sufficient to write an article. Therefore, it is not described here.

The basic idea is as follows: when performing a write operation, copy a copy first, and perform a write operation on the copy.

The read and traverse operations occur on the copies that exist when the operation occurs.

Read operations are not locked. Furthermore, we use the semantics of the java Memory Model to perform an elegant design.

The CopyOnWrite concurrent container is used in the concurrent scenario of reading, writing, and less. The CopyOnWrite container can only ensure the final consistency of data, but cannot guarantee the real-time consistency of data. Therefore, if you want to read the data you want to write, do not use the CopyOnWrite container.

For details, refer to the following article:

Concurrent chat-Copy-On-Write container in Java

Java memory model happens-before

 

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.