diff --git a/src/java/org/apache/commons/collections/NodeCachingLinkedList.java b/src/java/org/apache/commons/collections/NodeCachingLinkedList.java
new file mode 100644
index 000000000..824b5f7a3
--- /dev/null
+++ b/src/java/org/apache/commons/collections/NodeCachingLinkedList.java
@@ -0,0 +1,876 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Attic/NodeCachingLinkedList.java,v 1.1 2002/11/18 23:58:17 scolebourne Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/18 23:58:17 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * NodeCachingLinkedList
is a linked list implementation that
+ * provides better performance than java.util.LinkedList.
+ *
+ * This class differs from java.util.LinkedList in that internal Node + * objects used to hold the elements are not necessarily thrown away when an + * entry is removed from the list. Instead, they are cached, which allows this + * implementation to give better performance than java.util.LinkedList with a + * small space penalty. + *
+ * Note that this implementation is not synchronized. If multiple + * threads access a list concurrently, and at least one of the threads + * modifies the list structurally, it must be synchronized + * externally. + *
+ * The iterators returned by the this class's iterator
and
+ * listIterator
methods are fail-fast: if the list is
+ * structurally modified at any time after the iterator is created, in any way
+ * except through the Iterator's own remove
or add
methods,
+ * the iterator will throw a 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.
+ *
+ *
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 ConcurrentModificationException
on a best-effort basis.
+ * Therefore, it would be wrong to write a program that depended on this
+ * exception for its correctness: the fail-fast behavior of iterators
+ * should be used only to detect bugs.
+ *
+ * @author Jeff Varszegi
+ */
+public final class NodeCachingLinkedList
+ extends LinkedList
+ implements List, Cloneable, Serializable {
+
+ private static final int MINIMUM_MAXIMUM_CACHE_SIZE = 100;
+ private static final int DEFAULT_MAXIMUM_CACHE_SIZE = 1000000;
+
+ private Node cacheHeader = new Node(null, null, null);
+ private int cacheCount = 0;
+
+ private int maximumCacheSize = DEFAULT_MAXIMUM_CACHE_SIZE;
+
+ private Node header = new Node(null, null, null);
+ private int size = 0;
+
+ /**
+ * Constructs an empty list.
+ */
+ public NodeCachingLinkedList() {
+ 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 coll the collection whose elements are to be placed into this list.
+ * @throws NullPointerException if the specified collection is null.
+ */
+ public NodeCachingLinkedList(Collection coll) {
+ this();
+ addAll(coll);
+ }
+
+ /**
+ * Sets the maximum number of elements that may be held in the internal
+ * reusable node cache.
+ *
+ * @return the maximum cache size
+ */
+ public int getMaximumCacheSize() {
+ return maximumCacheSize;
+ }
+
+ /**
+ * Sets the maximum number of elements that may be held in the internal
+ * reusable node cache.
+ *
+ * @param maximumCacheSize the maximum cache size to set
+ */
+ public void setMaximumCacheSize(int maximumCacheSize) {
+ this.maximumCacheSize = maximumCacheSize;
+ }
+
+ /**
+ * Returns the first element in this list.
+ *
+ * @return the first object in the list
+ * @throws NoSuchElementException if this list is empty
+ */
+ public Object getFirst() {
+ if (size == 0) {
+ throw new NoSuchElementException();
+ }
+ else {
+ return header.next.element;
+ }
+ }
+
+ /**
+ * Returns the last element in this list.
+ *
+ * @return the last object in the list
+ * @throws NoSuchElementException if this list is empty
+ */
+ public Object 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, now removed
+ * @throws NoSuchElementException if this list is empty
+ */
+ public Object removeFirst() {
+ if (size == 0) {
+ throw new NoSuchElementException();
+ }
+ Node firstNode = header.next;
+ Object first = firstNode.element;
+
+ firstNode.next.previous = header;
+ header.next = firstNode.next;
+ size--;
+ modCount++;
+
+ if (cacheCount < maximumCacheSize) {
+
+ firstNode.element = null;
+ firstNode.next = cacheHeader.next;
+ cacheHeader.next = firstNode;
+ cacheCount++;
+ }
+
+ return first;
+ }
+
+ /**
+ * Removes and returns the last element from this list.
+ *
+ * @return the last element from this list, now removed
+ * @throws NoSuchElementException if this list is empty
+ */
+ public Object removeLast() {
+ if (size == 0) {
+ throw new NoSuchElementException();
+
+ }
+ Node lastNode = header.previous;
+ Object last = lastNode.element;
+
+ lastNode.previous.next = header;
+ header.previous = lastNode.previous;
+ size--;
+ modCount++;
+
+ if (cacheCount < maximumCacheSize) {
+ lastNode.element = null;
+ lastNode.previous = null;
+ lastNode.next = cacheHeader.next;
+ cacheHeader.next = lastNode;
+ cacheCount++;
+ }
+
+ return last;
+ }
+
+ /**
+ * Inserts the given element at the beginning of this list.
+ *
+ * @param obj the element to be inserted at the beginning of this list
+ */
+ public void addFirst(Object obj) {
+ Node newNode;
+
+ if (cacheCount > 0) {
+ newNode = cacheHeader.next;
+ cacheHeader.next = newNode.next;
+ newNode.element = obj;
+ newNode.next = header.next;
+ newNode.previous = header;
+ cacheCount--;
+ }
+ else {
+ newNode = new Node(obj, header.next, header);
+ }
+
+ newNode.previous.next = newNode;
+ newNode.next.previous = newNode;
+ size++;
+ modCount++;
+ }
+
+ /**
+ * Appends the given element to the end of this list. (Identical in
+ * function to the add
method; included only for consistency.)
+ *
+ * @param obj the element to be inserted at the end of this list
+ */
+ public void addLast(Object obj) {
+ Node newNode;
+
+ if (cacheCount > 0) {
+ newNode = cacheHeader.next;
+ cacheHeader.next = newNode.next;
+ newNode.element = obj;
+ newNode.next = header.next;
+ newNode.previous = header;
+ cacheCount--;
+ }
+ else {
+ newNode = new Node(obj, header, header.previous);
+ }
+
+
+
+ newNode.previous.next = newNode;
+ newNode.next.previous = newNode;
+ size++;
+ modCount++;
+ }
+
+ /**
+ * Returns true
if this list contains the specified element.
+ * More formally, returns true
if and only if this list contains
+ * at least one element e
such that (o==null ? e==null
+ * : o.equals(e))
.
+ *
+ * @param obj element whose presence in this list is to be tested
+ * @return true
if this list contains the specified element
+ */
+ public boolean contains(Object obj) {
+ return indexOf(obj) != -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.
+ *
+ * @param obj element to be appended to this list.
+ * @return true
(as per the general contract of
+ * Collection.add
)
+ */
+ public boolean add(Object obj) {
+ addLast(obj);
+ return true;
+ }
+
+ /**
+ * Removes the first occurrence of the specified element in this list. If
+ * the list does not contain the element, it is unchanged. More formally,
+ * removes the element with the lowest index i
such that
+ * (o==null ? get(i)==null : o.equals(get(i)))
(if such an
+ * element exists).
+ *
+ * @param obj element to be removed from this list, if present
+ * @return true
if the list contained the specified element
+ */
+ public boolean remove(Object obj) {
+ if (obj == null) {
+ for (Node e = header.next; e != header; e = e.next) {
+ if (e.element == null) {
+ remove(e);
+ return true;
+ }
+ }
+ }
+ else {
+ for (Node e = header.next; e != header; e = e.next) {
+ if (obj.equals(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. (This implies that the behavior of this call is undefined if
+ * the specified Collection is this list, and this list is nonempty.)
+ *
+ * @param coll the elements to be inserted into this list
+ * @return true
if this list changed as a result of the call
+ * @throws NullPointerException if the specified collection is null
+ */
+ public boolean addAll(Collection coll) {
+ return addAll(size, coll);
+ }
+
+ /**
+ * 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 first element
+ * from the specified collection
+ * @param coll elements to be inserted into this list
+ * @return true
if this list changed as a result of the call
+ * @throws IndexOutOfBoundsException if the specified index is out of
+ * range (index < 0 || index > size()
)
+ * @throws NullPointerException if the specified collection is null
+ */
+ public boolean addAll(int index, Collection coll) {
+ int numNew = coll.size();
+ if (numNew == 0)
+ return false;
+ modCount++;
+
+ Node successor = (index == size ? header : entry(index));
+ Node predecessor = successor.previous;
+ Iterator it = coll.iterator();
+ for (int i = 0; i < numNew; i++) {
+ Node e;
+ if (cacheCount > 0) {
+ e = cacheHeader.next;
+ cacheHeader.next = e.next;
+ e.element = it.next();
+ e.next = successor;
+ e.previous = predecessor;
+ }
+ else {
+ e = new Node(it.next(), 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() {
+ modCount++;
+ header.next = header.previous = header;
+ size = 0;
+ }
+
+ // Positional Access Operations
+
+ /**
+ * Returns the element at the specified position in this list.
+ *
+ * @param index index of element to return
+ * @return the element at the specified position in this list
+ *
+ * @throws IndexOutOfBoundsException if the specified index is is out of
+ * range (index < 0 || index >= size()
)
+ */
+ public Object get(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ Node 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.element;
+ }
+
+ /**
+ * Replaces the element at the specified position in this list with the
+ * specified element.
+ *
+ * @param index index of element to replace
+ * @param element element to be stored at the specified position
+ * @return the element previously at the specified position
+ * @throws IndexOutOfBoundsException if the specified index is out of
+ * range (index < 0 || index >= size()
)
+ */
+ public Object set(int index, Object element) {
+ Node e = entry(index);
+ Object 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 if the specified index is out of
+ * range (index < 0 || index > size()
)
+ */
+ public void add(int index, Object element) {
+ Node e = (index == size ? header : entry(index));
+ Node newNode;
+ if (cacheCount > 0) {
+ newNode = cacheHeader.next;
+ cacheHeader.next = newNode.next;
+ newNode.element = element;
+ newNode.next = e;
+ newNode.previous = e.previous;
+ }
+ else {
+ newNode = new Node(element, e, e.previous);
+ }
+
+ newNode.previous.next = newNode;
+ newNode.next.previous = newNode;
+ size++;
+ modCount++;
+ }
+
+ /**
+ * 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 removed
+ * @return the element previously at the specified position
+ *
+ * @throws IndexOutOfBoundsException if the specified index is out of
+ * range (index < 0 || index >= size()
)
+ */
+ public Object remove(int index) {
+ Node e = entry(index);
+ Object data = e.element;
+ remove(e);
+ return data;
+ }
+
+ /**
+ * Return the indexed entry.
+ */
+ private Node entry(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ Node 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 in this list of the first occurrence of the
+ * specified element, or -1 if the List does not contain this
+ * element. More formally, returns the lowest index i such that
+ * (o==null ? get(i)==null : o.equals(get(i)))
, or -1 if
+ * there is no such index.
+ *
+ * @param obj element to search for
+ * @return the index in this list of the first occurrence of the
+ * specified element, or -1 if the list does not contain this
+ * element
+ */
+ public int indexOf(Object obj) {
+ int index = 0;
+ if (obj == null) {
+ for (Node e = header.next; e != header; e = e.next) {
+ if (e.element == null)
+ return index;
+ index++;
+ }
+ }
+ else {
+ for (Node e = header.next; e != header; e = e.next) {
+ if (obj.equals(e.element))
+ return index;
+ index++;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index in this list of the last occurrence of the
+ * specified element, or -1 if the list does not contain this
+ * element. More formally, returns the highest index i such that
+ * (o==null ? get(i)==null : o.equals(get(i)))
, or -1 if
+ * there is no such index.
+ *
+ * @param obj element to search for
+ * @return the index in this list of the last occurrence of the
+ * specified element, or -1 if the list does not contain this
+ * element
+ */
+ public int lastIndexOf(Object obj) {
+ int index = size;
+ if (obj == null) {
+ for (Node e = header.previous; e != header; e = e.previous) {
+ index--;
+ if (e.element == null)
+ return index;
+ }
+ }
+ else {
+ for (Node e = header.previous; e != header; e = e.previous) {
+ index--;
+ if (obj.equals(e.element))
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns a list-iterator of the elements in this list (in proper
+ * sequence), starting at the specified position in the list.
+ * Obeys the general contract of List.listIterator(int)
.
+ *
+ * The list-iterator is fail-fast: if the list is structurally
+ * modified at any time after the Iterator is created, in any way except
+ * through the list-iterator's own remove
or add
+ * methods, the list-iterator will throw a
+ * 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.
+ *
+ * @param index index of first element to be returned from the
+ * list-iterator (by a call to next
)
+ * @return a ListIterator of the elements in this list (in proper
+ * sequence), starting at the specified position in the list
+ * @throws IndexOutOfBoundsException if index is out of range
+ * (index < 0 || index > size()
)
+ * @see List#listIterator(int)
+ */
+ public ListIterator listIterator(int index) {
+ return new ListItr(index);
+ }
+
+ private final class ListItr implements ListIterator {
+ private Node lastReturned = header;
+ private Node next;
+ private int nextIndex;
+ private int expectedModCount = modCount;
+
+ 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;
+ }
+ }
+
+ public boolean hasNext() {
+ return nextIndex != size;
+ }
+
+ public Object next() {
+ checkForComodification();
+ if (nextIndex == size)
+ throw new NoSuchElementException();
+
+ lastReturned = next;
+ next = next.next;
+ nextIndex++;
+ return lastReturned.element;
+ }
+
+ public boolean hasPrevious() {
+ return nextIndex != 0;
+ }
+
+ public Object previous() {
+ if (nextIndex == 0)
+ throw new NoSuchElementException();
+
+ lastReturned = next = next.previous;
+ nextIndex--;
+ checkForComodification();
+ return lastReturned.element;
+ }
+
+ public int nextIndex() {
+ return nextIndex;
+ }
+
+ public int previousIndex() {
+ return nextIndex - 1;
+ }
+
+ public void remove() {
+ checkForComodification();
+ try {
+ NodeCachingLinkedList.this.remove(lastReturned);
+ }
+ catch (NoSuchElementException e) {
+ throw new IllegalStateException();
+ }
+ if (next == lastReturned)
+ next = lastReturned.next;
+ else
+ nextIndex--;
+ lastReturned = header;
+ expectedModCount++;
+ }
+
+ public void set(Object o) {
+ if (lastReturned == header)
+ throw new IllegalStateException();
+ checkForComodification();
+ lastReturned.element = o;
+ }
+
+ public void add(Object o) {
+ checkForComodification();
+ lastReturned = header;
+
+ Node newNode;
+ if (cacheCount > 0) {
+ newNode = cacheHeader.next;
+ cacheHeader.next = newNode.next;
+ newNode.element = o;
+ newNode.next = next;
+ newNode.previous = next.previous;
+ }
+ else {
+ newNode = new Node(o, next, next.previous);
+ }
+
+ newNode.previous.next = newNode;
+ newNode.next.previous = newNode;
+ size++;
+ modCount++;
+
+ nextIndex++;
+ expectedModCount++;
+ }
+
+ private void checkForComodification() {
+ if (modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ private final static class Node implements Serializable {
+ Object element;
+ Node next;
+ Node previous;
+
+ Node(Object element, Node next, Node previous) {
+ this.element = element;
+ this.next = next;
+ this.previous = previous;
+ }
+ }
+
+
+ private Node addsBefore(Object o, Node e) {
+ Node newNode;
+ if (cacheCount > 0) {
+ newNode = cacheHeader.next;
+ cacheHeader.next = newNode.next;
+ newNode.element = o;
+ newNode.next = e;
+ newNode.previous = e.previous;
+ }
+ else {
+ newNode = new Node(o, e, e.previous);
+ }
+
+ newNode.previous.next = newNode;
+ newNode.next.previous = newNode;
+ size++;
+ modCount++;
+ return newNode;
+ }
+
+
+ private void remove(Node e) {
+ if (e == header) {
+ throw new NoSuchElementException();
+ }
+ e.previous.next = e.next;
+ e.next.previous = e.previous;
+ size--;
+ modCount++;
+
+ if (cacheCount < maximumCacheSize) {
+ e.element = null;
+ e.previous = null;
+ e.next = cacheHeader.next;
+ cacheHeader.next = e;
+ cacheCount++;
+ }
+ }
+
+ /**
+ * Returns a shallow copy of this NodeCachingLinkedList
. (The elements
+ * themselves are not cloned.)
+ *
+ * @return a shallow copy of this NodeCachingLinkedList
instance
+ */
+ public Object clone() {
+ NodeCachingLinkedList clone = new NodeCachingLinkedList();
+ clone.setMaximumCacheSize(maximumCacheSize);
+
+ // Initialize clone with our elements
+ for (Node e = header.next; e != header; e = e.next) {
+ clone.add(e.element);
+ }
+
+ return clone;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this list
+ * in the correct order.
+ *
+ * @return an array containing all of the elements in this list
+ * in the correct order
+ */
+ public Object[] toArray() {
+ Object[] result = new Object[size];
+ int i = 0;
+ for (Node e = header.next; e != header; e = e.next)
+ result[i++] = e.element;
+ return result;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this list in
+ * the correct order; the runtime type of the returned array is that of
+ * the specified array. If the list fits in the specified array, it
+ * is returned therein. Otherwise, a new array is allocated with the
+ * runtime type of the specified array and the size of this list.
+ *
+ * If the list fits in the specified array with room to spare + * (i.e., the array has more elements than the list), + * the element in the array immediately following the end of the + * collection is set to null. This is useful in determining the length + * of the list only if the caller knows that the list + * does not contain any null elements. + * + * @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 a is not a + * supertype of the runtime type of every element in this list + * @throws NullPointerException if the specified array is null + */ + public Object[] toArray(Object a[]) { + if (a.length < size) + a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); + int i = 0; + for (Node e = header.next; e != header; e = e.next) + a[i++] = e.element; + + if (a.length > size) + a[size] = null; + + return a; + } + +}