LinkedList source code - not commonly used methods

Keywords: Programming Java JDK

Here is a record of the methods that are not often used in LinkedList. Many of them are new in later versions. Learn more about the design ideas and usage of the implementation.

1. List to array

/**
 * Returns an array containing all the elements in this list in the correct order, from the first element to the last.
 * The returned array will be "safe" because this list does not retain references to it.
 * (In other words, this method mustAssign a new array)
 *  Therefore, the caller is free to modify the returned array.
 * <p>This method acts as bridge between array-based and collection-based
 * APIs.
 * @return an array containing all of the elements in this list
 *         in proper sequence
 */
public Object[] toArray() {
    Object[] result = new Object[size];
    int i = 0;
    for (Node<E> x = first; x != null; x = x.next)//Traversing linked list to assign value to array
        result[i++] = x.item;
    return result;
}
/**
 * Returns an array containing all elements in the list in the appropriate order (from the first element to the last element);
 * The runtime type of the returned array is the runtime type of the specified array.
 * Returns the list if it fits the specified array. 
 * Otherwise, a new array is allocated using the runtime type of the specified array and the size of the list.
 *
 * If the list is suitable for the specified array and has space left (that is, there are more elements in the array than the list),
 * beElements in the array immediately following the end of the listSet to {@ code null}.
 * (This is useful for determining the length of a list if the caller knows that the list does not contain any null elements.)
 *
 * This method acts as a bridge between array based and collection based API s. 
 * In addition, this method allows precise control over the run-time type of the output array, and in some cases can be used to save allocation costs.
 *
 * Suppose {@ code x} is a list of known strings only. 
 * The following code can be used to dump the list into the newly allocated {@ code String} array:
 * <pre>
 *     String[] y = x.toArray(new String[0]);</pre>
 * Note that {@ code toArray (new Object [0])} is functionally the same as {@ code toarray()}.
 *
 * @param a the array into which the elements of the list are to
 *          be stored, if it is big enough; otherwise, a new array of the
 *          same runtime type is allocated for this purpose.
 * @return an array containing the elements of the list
 * @throws ArrayStoreException if the runtime type of the specified array
 *         is not a supertype of the runtime type of every element in
 *         this list
 * @throws NullPointerException if the specified array is null
 */
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    if (a.length < size)//Array size is smaller than list size, allocate a new array
        a = (T[])java.lang.reflect.Array.newInstance(
                            a.getClass().getComponentType(), size);
    int i = 0;
    Object[] result = a;
    for (Node<E> x = first; x != null; x = x.next)
        result[i++] = x.item;//Starting from 0, if there are elements before the array, they will be overwritten

    if (a.length > size)
        a[size] = null;//The element in the array immediately following the end of the list, but not all

    return a;
}

Add a test code:

public class LinkedListTest01 {

    public static void main(String[] args) {
        List<String> list = new LinkedList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");

        String[] p = new String[9];
        Arrays.fill(p, "11");
        System.out.println(Arrays.toString(p));
        String[] r = list.toArray(p);
        System.out.println(Arrays.toString(r));
    }
}

Output:[11, 11, 11, 11, 11, 11, 11, 11, 11]
[1, 2, 3, 4, 5, 6, null, 11, 11]

2. Queue operation

Take a look at the linkedList class declaration. It inherits Deque and Deque inherits Queue, so there will be some Queue operations.

/**
 * Retrieves but does not delete the header (first element) of this list.
 * @return the head of this list, or {@code null} if this list is empty
 * @since 1.5
 */
public E peek() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
}

/**
 * Retrieves but does not delete the header (first element) of this list.If the list is empty, an exception will be thrown
 * @return the head of this list
 * @throws NoSuchElementException if this list is empty
 * @since 1.5
 */
public E element() {
    return getFirst();//Directly call the method to query the first element of the list
}

/**
 * Retrieve anddeleteThe header (first element) of this list.
 * @return the head of this list, or {@code null} if this list is empty
 * @since 1.5
 */
public E poll() {
    final Node<E> f = first;
    return (f == null) ? null : unlinkFirst(f);//Delete the first non empty node
}

/**
 * Retrieve and delete the header (first element) of this list. (this is also recorded in common methods)
 * @return the head of this list
 * @throws NoSuchElementException if this list is empty
 * @since 1.5
 */
public E remove() {
    return removeFirst();
}

/**
 *Adds the specified element to the end (last element) of this list.
 * @param e the element to add
 * @return {@code true} (as specified by {@link Queue#offer})
 * @since 1.5
 */
public boolean offer(E e) {
    return add(e);//Directly calls the method that inserts the specified element
}

3. Two terminal queue operation

/**
 * Inserts the specified element in front of this list.
 * @param e the element to insert
 * @return {@code true} (as specified by {@link Deque#offerFirst})
 * @since 1.6
 */
public boolean offerFirst(E e) {
    addFirst(e);
    return true;
}

/**
 * Inserts the specified element at the end of this list.
 * @param e the element to insert
 * @return {@code true} (as specified by {@link Deque#offerLast})
 * @since 1.6
 */
public boolean offerLast(E e) {
    addLast(e);
    return true;
}

/**
 * Retrieve but do not delete the first element of this list. If this list is empty, {@ code null} will be returned.
 * @return the first element of this list, or {@code null}
 *         if this list is empty
 * @since 1.6
 */
public E peekFirst() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
 }

/**
 * Retrieve but do not delete the last element of this list. If this list is empty, {@ code null} will be returned.
 *
 * @return the last element of this list, or {@code null}
 *         if this list is empty
 * @since 1.6
 */
public E peekLast() {
    final Node<E> l = last;
    return (l == null) ? null : l.item;
}

/**
 * Retrieve and delete the first element of this list, and if the list is empty, {@ code null} is returned.
 * @return the first element of this list, or {@code null} if
 *     this list is empty
 * @since 1.6
 */
public E pollFirst() {
    final Node<E> f = first;
    return (f == null) ? null : unlinkFirst(f);
}

/**
 * Retrieve and delete the last element of this list, and if the list is empty, {@ code null} is returned.
 * @return the last element of this list, or {@code null} if
 *     this list is empty
 * @since 1.6
 */
public E pollLast() {
    final Node<E> l = last;
    return (l == null) ? null : unlinkLast(l);
}

/**
 * Press elements into thestack.  In other words, insert elements in front of this list.
 * <p>This method is equivalent to {@link #addFirst}.
 * @param e the element to push
 * @since 1.6
 */
public void push(E e) {
    addFirst(e);
}

/**
 * Represented from this liststackAn element pops up in. In other words, delete and return the first element of this list.
 * <p>This method is equivalent to {@link #removeFirst()}.
 * @return the element at the front of this list (which is the top
 *         of the stack represented by this list)
 * @throws NoSuchElementException if this list is empty
 * @since 1.6
 */
public E pop() {
    return removeFirst();
}

/**
 * Deletes the first occurrence of the specified element in this list (when traversing the list from start to finish).
 * If the list does not contain the element, it remains unchanged.
 * @param o element to be removed from this list, if present
 * @return {@code true} if the list contained the specified element
 * @since 1.6
 */
public boolean removeFirstOccurrence(Object o) {
    return remove(o);
}

/**
 * deleteThe last occurrence of the specified element in this list(When traversing the list from top to bottom (determine which is the last)).  
 * If the list does not contain the element, it remains unchanged.
 * @param o element to be removed from this list, if present
 * @return {@code true} if the list contained the specified element
 * @since 1.6
 */
public boolean removeLastOccurrence(Object o) {//There is no other implementation. Find out the last logical implementation
    if (o == null) {
        for (Node<E> x = last; x != null; x = x.prev) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = last; x != null; x = x.prev) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}

It can be seen from the above source code that most of the functions of these queue operations can be realized by calling the existing common methods, so the common methods should be understood and mastered.

4. Cloning method

/**
 * Returns a shallow copy of this {@ code LinkedList}. (the element itself is not cloned.)
 * @return a shallow copy of this {@code LinkedList} instance
 */
public Object clone() {
    LinkedList<E> clone = superClone();

    // Put clone into "virgin" state
    clone.first = clone.last = null;
    clone.size = 0;
    clone.modCount = 0;

    // Initialize clone with our elements
    for (Node<E> x = first; x != null; x = x.next)
        clone.add(x.item);

    return clone;
}
@SuppressWarnings("unchecked")
private LinkedList<E> superClone() {
    try {
        return (LinkedList<E>) super.clone();
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e);
    }//Catch one exception and throw another
}

5. Serialization

/**
 * Save the state of this {@ code LinkedList} instance to the stream (that is, serialize it).
 * @serialData The size of the list (the number of elements it
 *             contains) is emitted (int), followed by all of its
 *             elements (each an Object) in the proper order.
 */
private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException {
    // Write out any hidden serialization magic
    s.defaultWriteObject();

    // Write out size
    s.writeInt(size);

    // Write out all elements in the proper order.
    for (Node<E> x = first; x != null; x = x.next)
        s.writeObject(x.item);//One element, one element writing
}

/**
 * Refactor the {@ code LinkedList} instance from the stream (that is, deserialize it).
 */
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    // Read in any hidden serialization magic
    s.defaultReadObject();

    // Read in size
    int size = s.readInt();

    // Read in all elements in the proper order.
    for (int i = 0; i < size; i++)
        linkLast((E)s.readObject());//The reading of one element, and then the ending is added to the list
}

6. Splitter

This is introduced by jdk 1.8. I won't understand it for now.

Posted by teamfox20 on Wed, 03 Jun 2020 08:10:25 -0700