ArrayList source view

One, ArrayList introduction

The frequently used collection framework ArrayList, inherited from the AbstractList abstract class, implements the List interface, has the functions of adding, deleting, modifying, and checking lists, and realizing the RandomAccess empty interface (the empty interface is used for marking, and the underlying algorithm determines whether instanceof implements the marking interface selection Different algorithms) have fast access function, realize Cloneable empty interface (marker interface), have data copy function

public class ArrayList<E> 
		extends AbstractList<E>
		implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    
    

1. The underlying implementation principle

The bottom layer is an array implementation. The default structure creation size uses the default DEFAULT_CAPACITY capacity of 10, and it dynamically expands with the increase of data (each time you increase the length of the original array by half, determine whether it is enough, if the increase by half is not enough, use size+ 1 or size + numNew for precise length expansion), and then copy the old data to the new container; because the bottom layer is an array, the storage addresses in the memory are connected, so the query efficiency is high, and the addition and deletion efficiency is low (may need to expand when increasing , You need to copy and move the content when you delete it)

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {
    
    };

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    
    };

Expand the grow method, minCapacity really needs the size of the capacity

    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    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);
    }

Two, method introduction

1. Construction method ArrayList/ArrayList(int)/ArrayList(Collection)

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
    
    
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
/**
     * 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) {
    
    
        if (initialCapacity > 0) {
    
    
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
    
    
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
    
    
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * 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();
        if ((size = elementData.length) != 0) {
    
    
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
    
    
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

2. New element add/addAll

The ensureCapacityInternal method internally determines whether the capacity is sufficient, and expands if it is not enough

rangeCheckForAdd judges whether it is out of range, if it is out of range, an IndexOutOfBoundsException will be thrown

System.arraycopy copy mobile data

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
    
    
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
	/**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
    
    
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }
	/**
     * Appends all of the elements in the specified collection to the end of
     * this list, in the order that they are returned by the
     * specified collection's Iterator.  The behavior of this operation is
     * undefined if the specified collection is modified while the operation
     * is in progress.  (This implies that the behavior of this call is
     * undefined if the specified collection is this list, and this
     * list is nonempty.)
     *
     * @param c collection containing elements to be added to this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(Collection<? extends E> c) {
    
    
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * Inserts all of the elements in the specified collection into this
     * list, starting at the specified position.  Shifts the element
     * currently at that position (if any) and any subsequent elements to
     * the right (increases their indices).  The new elements will appear
     * in the list in the order that they are returned by the
     * specified collection's iterator.
     *
     * @param index index at which to insert the first element from the
     *              specified collection
     * @param c collection containing elements to be added to this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(int index, Collection<? extends E> c) {
    
    
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

3. Read the data

rangeCheck determines whether it is out of range

    /**
     * Returns the element at the specified position in this list.
     *
     * @param  index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
    
    
        rangeCheck(index);

        return elementData(index);
    }

4. Modify the data

    /**
     * Replaces the element at the specified position in this list with
     * the specified element.
     *
     * @param index index of the element to replace
     * @param element element to be stored at the specified position
     * @return the element previously at the specified position
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
    
    
        rangeCheck(index);

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

5. Delete data

/**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    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; // clear to let GC do its work

        return oldValue;
    }

    /**
     * Removes the first occurrence of the specified element from this list,
     * if it is present.  If the list does not contain the element, it is
     * unchanged.  More formally, removes the element with the lowest index
     * <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
     * (if such an element exists).  Returns <tt>true</tt> if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     *
     * @param o element to be removed from this list, if present
     * @return <tt>true</tt> if this list contained the specified element
     */
    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;
    }

Delete elements that intersect with the given set

    /**
     * Removes from this list all of its elements that are contained in the
     * specified collection.
     *
     * @param c collection containing elements to be removed from this list
     * @return {@code true} if this list changed as a result of the call
     * @throws ClassCastException if the class of an element of this list
     *         is incompatible with the specified collection
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this list contains a null element and the
     *         specified collection does not permit null elements
     * (<a href="Collection.html#optional-restrictions">optional</a>),
     *         or if the specified collection is null
     * @see Collection#contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
    
    
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

6. Traverse the data

for loop

	for (int i = 0; i < listData.size(); i++) {
    
    
		//do something
	}

iterator/listIterator iterator

	Iterator<String> iterator = listData.iterator();
	while (iterator.hasNext()) {
    
    
		System.out.println(iterator.next());
	}
	ListIterator<String> listIterator = listData.listIterator();
	while (listIterator .hasNext()) {
    
    
		System.out.println(listIterator.next());
	}

ListIterator is more powerful than the parent interface Iterator, and can also operate on data during traversal
Insert picture description here
Insert picture description here

to sum up

In the interview, in addition to asking about the underlying implementation principle, expansion, etc., you will also encounter deleting the same element in the list or deleting a specified element in the list; completing the written test is only one of them, if you can solve it in terms of time and space complexity , It is possible that the interviewer will shine

Guess you like

Origin blog.csdn.net/nongminkouhao/article/details/108490295