877 lines · 28.8 KB · Java
RawDownload
/* * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt.util; import java.util.AbstractSequentialList;import java.util.Collection;import java.util.ConcurrentModificationException;import java.util.Deque;import java.util.Iterator;import java.util.List;import java.util.ListIterator;import java.util.NoSuchElementException; /** * Linked list implementation of the <tt>List</tt> interface.  Implements all * optional list operations, and permits all elements (including * <tt>null</tt>).  In addition to implementing the <tt>List</tt> interface, * the <tt>IdentityLinkedList</tt> class provides uniformly named methods to * <tt>get</tt>, <tt>remove</tt> and <tt>insert</tt> an element at the * beginning and end of the list.  These operations allow linked lists to be * used as a stack, {@linkplain Queue queue}, or {@linkplain Deque * double-ended queue}. <p> * * The class implements the <tt>Deque</tt> interface, providing * first-in-first-out queue operations for <tt>add</tt>, * <tt>poll</tt>, along with other stack and deque operations.<p> * * All of the operations perform as could be expected for a doubly-linked * list.  Operations that index into the list will traverse the list from * the beginning or the end, whichever is closer to the specified index.<p> * * <p><strong>Note that this implementation is not synchronized.</strong> * If multiple threads access a linked list concurrently, and at least * one of the threads modifies the list structurally, it <i>must</i> be * synchronized externally.  (A structural modification is any operation * that adds or deletes one or more elements; merely setting the value of * an element is not a structural modification.)  This is typically * accomplished by synchronizing on some object that naturally * encapsulates the list. * * If no such object exists, the list should be "wrapped" using the * {@link Collections#synchronizedList Collections.synchronizedList} * method.  This is best done at creation time, to prevent accidental * unsynchronized access to the list:<pre> *   List list = Collections.synchronizedList(new IdentityLinkedList(...));</pre> * * <p>The iterators returned by this class's <tt>iterator</tt> and * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is * structurally modified at any time after the iterator is created, in * any way except through the Iterator's own <tt>remove</tt> or * <tt>add</tt> methods, the iterator will throw a {@link * ConcurrentModificationException}.  Thus, in the face of concurrent * modification, the iterator fails quickly and cleanly, rather than * risking arbitrary, non-deterministic behavior at an undetermined * time in the future. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification.  Fail-fast iterators * throw <tt>ConcurrentModificationException</tt> on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this * exception for its correctness:   <i>the fail-fast behavior of iterators * should be used only to detect bugs.</i> */ public class IdentityLinkedList<E>    extends AbstractSequentialList<E>    implements List<E>, Deque<E>{    private transient Entry<E> header = new Entry<E>(null, null, null);    private transient int size = 0;     /**     * Constructs an empty list.     */    public IdentityLinkedList() {        header.next = header.previous = header;    }     /**     * 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 IdentityLinkedList(Collection<? extends E> c) {        this();        addAll(c);    }     /**     * Returns the first element in this list.     *     * @return the first element in this list     * @throws NoSuchElementException if this list is empty     */    public E getFirst() {        if (size==0)            throw new NoSuchElementException();         return header.next.element;    }     /**     * Returns the last element in this list.     *     * @return the last element in this list     * @throws NoSuchElementException if this list is empty     */    public E getLast()  {        if (size==0)            throw new NoSuchElementException();         return header.previous.element;    }     /**     * Removes and returns the first element from this list.     *     * @return the first element from this list     * @throws NoSuchElementException if this list is empty     */    public E removeFirst() {        return remove(header.next);    }     /**     * Removes and returns the last element from this list.     *     * @return the last element from this list     * @throws NoSuchElementException if this list is empty     */    public E removeLast() {        return remove(header.previous);    }     /**     * Inserts the specified element at the beginning of this list.     *     * @param e the element to add     */    public void addFirst(E e) {        addBefore(e, header.next);    }     /**     * Appends the specified element to the end of this list.     *     * <p>This method is equivalent to {@link #add}.     *     * @param e the element to add     */    public void addLast(E e) {        addBefore(e, header);    }     /**     * Returns <tt>true</tt> if this list contains the specified element.     * More formally, returns <tt>true</tt> if and only if this list contains     * at least one element <tt>e</tt> such that     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o == e)</tt>.     *     * @param o element whose presence in this list is to be tested     * @return <tt>true</tt> if this list contains the specified element     */    public boolean contains(Object o) {        return indexOf(o) != -1;    }     /**     * Returns the number of elements in this list.     *     * @return the number of elements in this list     */    public int size() {        return size;    }     /**     * Appends the specified element to the end of this list.     *     * <p>This method is equivalent to {@link #addLast}.     *     * @param e element to be appended to this list     * @return <tt>true</tt> (as specified by {@link Collection#add})     */    public boolean add(E e) {        addBefore(e, header);        return true;    }     /**     * Removes the first occurrence of the specified element from this list,     * if it is present.  If this list does not contain the element, it is     * unchanged.  More formally, removes the element with the lowest index     * <tt>i</tt> such that <tt>get(i)==o</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) {        for (Entry<E> e = header.next; e != header; e = e.next) {            if (o == e.element) {                remove(e);                return true;            }        }        return false;    }     /**     * 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.  (Note that this will occur if the specified collection is     * this list, and it's 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) {        return addAll(size, c);    }     /**     * 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) {        if (index < 0 || index > size)            throw new IndexOutOfBoundsException("Index: "+index+                                                ", Size: "+size);        Object[] a = c.toArray();        int numNew = a.length;        if (numNew==0)            return false;        modCount++;         Entry<E> successor = (index==size ? header : entry(index));        Entry<E> predecessor = successor.previous;        for (int i=0; i<numNew; i++) {            Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);            predecessor.next = e;            predecessor = e;        }        successor.previous = predecessor;         size += numNew;        return true;    }     /**     * Removes all of the elements from this list.     */    public void clear() {        Entry<E> e = header.next;        while (e != header) {            Entry<E> next = e.next;            e.next = e.previous = null;            e.element = null;            e = next;        }        header.next = header.previous = header;        size = 0;        modCount++;    }      // Positional Access Operations     /**     * 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) {        return entry(index).element;    }     /**     * 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) {        Entry<E> e = entry(index);        E oldVal = e.element;        e.element = element;        return oldVal;    }     /**     * 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) {        addBefore(element, (index==size ? header : entry(index)));    }     /**     * Removes the element at the specified position in this list.  Shifts any     * subsequent elements to the left (subtracts one from their indices).     * Returns the element that was removed from the list.     *     * @param index the index of the element to be removed     * @return the element previously at the specified position     * @throws IndexOutOfBoundsException {@inheritDoc}     */    public E remove(int index) {        return remove(entry(index));    }     /**     * Returns the indexed entry.     */    private Entry<E> entry(int index) {        if (index < 0 || index >= size)            throw new IndexOutOfBoundsException("Index: "+index+                                                ", Size: "+size);        Entry<E> e = header;        if (index < (size >> 1)) {            for (int i = 0; i <= index; i++)                e = e.next;        } else {            for (int i = size; i > index; i--)                e = e.previous;        }        return e;    }      // Search Operations     /**     * Returns the index of the first occurrence of the specified element     * in this list, or -1 if this list does not contain the element.     * More formally, returns the lowest index <tt>i</tt> such that     * <tt>get(i)==o</tt>,     * or -1 if there is no such index.     *     * @param o element to search for     * @return the index of the first occurrence of the specified element in     *         this list, or -1 if this list does not contain the element     */    public int indexOf(Object o) {        int index = 0;        for (Entry e = header.next; e != header; e = e.next) {            if (o == e.element) {                return index;            }            index++;        }        return -1;    }     /**     * Returns the index of the last occurrence of the specified element     * in this list, or -1 if this list does not contain the element.     * More formally, returns the highest index <tt>i</tt> such that     * <tt>get(i)==o</tt>,     * or -1 if there is no such index.     *     * @param o element to search for     * @return the index of the last occurrence of the specified element in     *         this list, or -1 if this list does not contain the element     */    public int lastIndexOf(Object o) {        int index = size;        for (Entry e = header.previous; e != header; e = e.previous) {            index--;            if (o == e.element) {                return index;            }        }        return -1;    }     // Queue operations.     /**     * Retrieves, but does not remove, the head (first element) of this list.     * @return the head of this list, or <tt>null</tt> if this list is empty     * @since 1.5     */    public E peek() {        if (size==0)            return null;        return getFirst();    }     /**     * Retrieves, but does not remove, the head (first element) of this list.     * @return the head of this list     * @throws NoSuchElementException if this list is empty     * @since 1.5     */    public E element() {        return getFirst();    }     /**     * Retrieves and removes the head (first element) of this list     * @return the head of this list, or <tt>null</tt> if this list is empty     * @since 1.5     */    public E poll() {        if (size==0)            return null;        return removeFirst();    }     /**     * Retrieves and removes the head (first element) of this list.     *     * @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 as the tail (last element) of this list.     *     * @param e the element to add     * @return <tt>true</tt> (as specified by {@link Queue#offer})     * @since 1.5     */    public boolean offer(E e) {        return add(e);    }     // Deque operations    /**     * Inserts the specified element at the front of this list.     *     * @param e the element to insert     * @return <tt>true</tt> (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.

Lines 1–500 of 877.