java.util.LinkedList是一个基于双向链表的容器类型。这里将罗列出其具体实现并分析其原理。
类声明:
public class LinkedList<T> extends AbstractSequentialList<T>
implements List<T>, Deque<T>, Cloneable, Serializable
private static final long serialVersionUID = 876323262645176354L;
transient Entry<T> first;
transient Entry<T> last;
transient int size = 0;
成员变量中定义了序列化ID,首节点first,尾节点last和容器当前大小size,size为容器中当前元素的个数。
其中有两点需要注意:
(一)首节点,尾节点和大小不作为序列化成员,声明为transient变量。
(二)其中Entry<T>为一个泛型容器类,是链表节点的类型,其声明为LinkedList的静态内部类,定义如下:
private static final class Entry<T> {
T data;
Entry<T> next;
Entry<T> previous;
Entry(T data)
{
this.data = data;
}
}
Entry类型结构清晰,是一个标志性的双向链表。包含前驱和后继的引用。构造函数用于初始化值。
LinkedList中定义了针对节点对象的获取,移除函数,定义如下:
136: Entry<T> getEntry(int n)
137: {
138: Entry<T> e;
139: if (n < size / 2)
140: {
141: e = first;
142: // n less than size/2, iterate from start
143: while (n-- > 0)
144: e = e.next;
145: }
146: else
147: {
148: e = last;
149: // n greater than size/2, iterate from end
150: while (++n < size)
151: e = e.previous;
152: }
153: return e;
154: }
163: void removeEntry(Entry<T> e)
164: {
165: modCount++;
166: size--;
167: if (size == 0)
168: first = last = null;
169: else
170: {
171: if (e == first)
172: {
173: first = e.next;
174: e.next.previous = null;
175: }
176: else if (e == last)
177: {
178: last = e.previous;
179: e.previous.next = null;
180: }
181: else
182: {
183: e.next.previous = e.previous;
184: e.previous.next = e.next;
185: }
186: }
187: }
这里需要留意,对链表进行修改的操作中都有一个ModCount的变量在自增,它是Modification Count的意思,是一个记录链表修改次数的计数器。它的作用是帮助检测链表被修改的情况。
195: private void checkBoundsInclusive(int index)
196: {
197: if (index < 0 || index > size)
198: throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
199: + size);
200: }
208: private void checkBoundsExclusive(int index)
209: {
210: if (index < 0 || index >= size)
211: throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
212: + size);
213: }
218: public LinkedList()
219: {
220: }
229: public LinkedList(Collection<? extends T> c)
230: {
231: addAll(c);
232: }
其中,addAll有两个定义,参数为容器类型定义如下:
430: public boolean addAll(Collection<? extends T> c)
431: {
432: return addAll(size, c);
433: }
另一个为:
445: public boolean addAll(int index, Collection<? extends T> c)
446: {
447: checkBoundsInclusive(index);
448: int csize = c.size();
449:
450: if (csize == 0)
451: return false;
452:
453: Iterator<? extends T> itr = c.iterator();
454:
455: // Get the entries just before and after index. If index is at the start
456: // of the list, BEFORE is null. If index is at the end of the list, AFTER
457: // is null. If the list is empty, both are null.
458: Entry<T> after = null;
459: Entry<T> before = null;
460: if (index != size)
461: {
462: after = getEntry(index);
463: before = after.previous;
464: }
465: else
466: before = last;
467:
468: // Create the first new entry. We do not yet set the link from `before'
469: // to the first entry, in order to deal with the case where (c == this).
470: // [Actually, we don't have to handle this case to fufill the
471: // contract for addAll(), but Sun's implementation appears to.]
472: Entry<T> e = new Entry<T>(itr.next());
473: e.previous = before;
474: Entry<T> prev = e;
475: Entry<T> firstNew = e;
476:
477: // Create and link all the remaining entries.
478: for (int pos = 1; pos < csize; pos++)
479: {
480: e = new Entry<T>(itr.next());
481: e.previous = prev;
482: prev.next = e;
483: prev = e;
484: }
485:
486: // Link the new chain of entries into the list.
487: modCount++;
488: size += csize;
489: prev.next = after;
490: if (after != null)
491: after.previous = e;
492: else
493: last = e;
494:
495: if (before != null)
496: before.next = firstNew;
497: else
498: first = firstNew;
499: return true;
500: }
如上方法对容器使用迭代器进行遍历,逐一将对象复制拷贝到当前链表中。
然后类型还定义了针对首尾节点的单独操作,获取,添加和删除操作,定义如下:
240: public T getFirst()
241: {
242: if (size == 0)
243: throw new NoSuchElementException();
244: return first.data;
245: }
253: public T getLast()
254: {
255: if (size == 0)
256: throw new NoSuchElementException();
257: return last.data;
258: }
266: public T removeFirst()
267: {
268: if (size == 0)
269: throw new NoSuchElementException();
270: modCount++;
271: size--;
272: T r = first.data;
273:
274: if (first.next != null)
275: first.next.previous = null;
276: else
277: last = null;
278:
279: first = first.next;
280:
281: return r;
282: }
283:
290: public T removeLast()
291: {
292: if (size == 0)
293: throw new NoSuchElementException();
294: modCount++;
295: size--;
296: T r = last.data;
297:
298: if (last.previous != null)
299: last.previous.next = null;
300: else
301: first = null;
302:
303: last = last.previous;
304:
305: return r;
306: }
313: public void addFirst(T o)
314: {
315: Entry<T> e = new Entry(o);
316:
317: modCount++;
318: if (size == 0)
319: first = last = e;
320: else
321: {
322: e.next = first;
323: first.previous = e;
324: first = e;
325: }
326: size++;
327: }
334: public void addLast(T o)
335: {
336: addLastEntry(new Entry<T>(o));
337: }
其中addLastEntry方法定义如下:
344: private void addLastEntry(Entry<T> e)
345: {
346: modCount++;
347: if (size == 0)
348: first = last = e;
349: else
350: {
351: e.previous = last;
352: last.next = e;
353: last = e;
354: }
355: size++;
356: }
这里之所以单独将addLastEntry()方法提出来定义是因为链表的新元素默认在尾部添加,并且在添加元素的方法boolean add(T o)中再次使用了addLastEntry()方法:
393: public boolean add(T o)
394: {
395: addLastEntry(new Entry<T>(o));
396: return true;
397: }
同时LinkedList还支持插入元素功能,可以指定一个索引作为插入位置,方法名同样为add,但是无返回值,参数为int index和T o:
553: public void add(int index, T o)
554: {
555: checkBoundsInclusive(index);
556: Entry<T> e = new Entry<T>(o);
557:
558: if (index < size)
559: {
560: modCount++;
561: Entry<T> after = getEntry(index);
562: e.next = after;
563: e.previous = after.previous;
564: if (after.previous == null)
565: first = e;
566: else
567: after.previous.next = e;
568: after.previous = e;
569: size++;
570: }
571: else
572: addLastEntry(e);
573: }
很有意思的是,还有一个方法叫offer(T value)定义如下:
719: public boolean offer(T value)
720: {
721: return add(value);
722: }
它和add(T o)有什么不同呢?
该容器中还有三个返回首元素的方法,但是对于容器为空时,它们的返回值有所不同:
732: public T element()
733: {
734: return getFirst();
735: }
element()方法返回首节点,但不删除首节点。如果链表为空,抛出NoSuchElementException。
745: public T peek()
746: {
747: if (size == 0)
748: return null;
749: return getFirst();
750: }
peek()方法,返回首节点,但不删除它。如果链表为空,返回null。
759: public T poll()
760: {
761: if (size == 0)
762: return null;
763: return removeFirst();
764: }
poll()方法返回首节点,但删除首节点,如果链表为空,返回null。
接下来,容器中定义了两个序列化方法。分别为写入和读取数据流。
当容器序列化时,成员函数writeObject将会把链表作为数据顺序写入输出流,定义如下:
786: private void writeObject(ObjectOutputStream s) throws IOException
787: {
788: s.defaultWriteObject();
789: s.writeInt(size);
790: Entry<T> e = first;
791: while (e != null)
792: {
793: s.writeObject(e.data);
794: e = e.next;
795: }
796: }
如下为从输入流中读入链表的方法:
807: private void readObject(ObjectInputStream s)
808: throws IOException, ClassNotFoundException
809: {
810: s.defaultReadObject();
811: int i = s.readInt();
812: while (--i >= 0)
813: addLastEntry(new Entry<T>((T) s.readObject()));
814: }
在LinkedList结尾,定义了一个非常重要的内部类,迭代器Iterator。
类声明:
private final class LinkedListItr<I>
实现接口:
implements ListIterator<I>
成员变量:
827: private int knownMod = modCount;
830: private Entry<I> next;
833: private Entry<I> previous;
836: private Entry<I> lastReturned;
839: private int position;
其中定义了构造方法:
LinkedListItr(int index)
847: {
848: if (index == size)
849: {
850: next = null;
851: previous = (Entry<I>) last;
852: }
853: else
854: {
855: next = (Entry<I>) getEntry(index);
856: previous = next.previous;
857: }
858: position = index;
859: }
迭代器中有一个方法值得注意:
866: private void checkMod()
867: {
868: if (knownMod != modCount)
869: throw new ConcurrentModificationException();
870: }
这是检测链表是否被修改的方法,用于在多线程和迭代过程中监测链表的情况。
然后就是我们常用的hasNext()和next()方法:
897: public boolean hasNext()
898: {
899: return (next != null);
900: }
919: public I next()
920: {
921: checkMod();
922: if (next == null)
923: throw new NoSuchElementException();
924: position++;
925: lastReturned = previous = next;
926: next = lastReturned.next;
927: return lastReturned.data;
928: }
迭代器还提供了移除和添加元素的方法:
954: public void remove()
955: {
956: checkMod();
957: if (lastReturned == null)
958: throw new IllegalStateException();
959:
960: // Adjust the position to before the removed element, if the element
961: // being removed is behind the cursor.
962: if (lastReturned == previous)
963: position--;
964:
965: next = lastReturned.next;
966: previous = lastReturned.previous;
967: removeEntry((Entry<T>) lastReturned);
968: knownMod++;
969:
970: lastReturned = null;
971: }
979: public void add(I o)
980: {
981: checkMod();
982: modCount++;
983: knownMod++;
984: size++;
985: position++;
986: Entry<I> e = new Entry<I>(o);
987: e.previous = previous;
988: e.next = next;
989:
990: if (previous != null)
991: previous.next = e;
992: else
993: first = (Entry<T>) e;
994:
995: if (next != null)
996: next.previous = e;
997: else
998: last = (Entry<T>) e;
999:
1000: previous = e;
1001: lastReturned = null;
1002: }
如果希望从后往前遍历链表,LinkedList还提供了倒序迭代器:
类定义如下:
public Iterator<T> descendingIterator()
其成员函数与之前类似,这里省去,可以参考文后提供的源代码。
最后还有两个LinkedList的成员函数比较有意思:
1231: public boolean removeFirstOccurrence(Object o)
1232: {
1233: return remove(o);
1234: }
1245: public boolean removeLastOccurrence(Object o)
1246: {
1247: Entry<T> e = last;
1248: while (e != null)
1249: {
1250: if (equals(o, e.data))
1251: {
1252: removeEntry(e);
1253: return true;
1254: }
1255: e = e.previous;
1256: }
1257: return false;
1258: }
这是两个删除元素的方法,类似于remove(),其定义如下:
406: public boolean remove(Object o)
407: {
408: Entry<T> e = first;
409: while (e != null)
410: {
411: if (equals(o, e.data))
412: {
413: removeEntry(e);
414: return true;
415: }
416: e = e.next;
417: }
418: return false;
419: }
可以发现,removeFirstOccurrence()就是remove(),是从低索引开始,移除第一个匹配的元素。但是removeLastOccurrence()则是从高索引开始,依序向前,移除第一个匹配的值。一个从前往后,一个从后往前。
本文省略了一些成员方法的介绍,大家可以通过后边的源代码自行了解。
这是我读源代码的第一篇文章,必定有出入,我将在以后不断更新文章的内容。
源代码一览
源代码来源:http://developer.classpath.org/doc/java/util/LinkedList-source.html
1: /* LinkedList.java -- Linked list implementation of the List interface
2: Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
3:
4: This file is part of GNU Classpath.
5:
6: GNU Classpath is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU Classpath is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Classpath; see the file COPYING. If not, write to the
18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19: 02110-1301 USA.
20:
21: Linking this library statically or dynamically with other modules is
22: making a combined work based on this library. Thus, the terms and
23: conditions of the GNU General Public License cover the whole
24: combination.
25:
26: As a special exception, the copyright holders of this library give you
27: permission to link this library with independent modules to produce an
28: executable, regardless of the license terms of these independent
29: modules, and to copy and distribute the resulting executable under
30: terms of your choice, provided that you also meet, for each linked
31: independent module, the terms and conditions of the license of that
32: module. An independent module is a module which is not derived from
33: or based on this library. If you modify this library, you may extend
34: this exception to your version of the library, but you are not
35: obligated to do so. If you do not wish to do so, delete this
36: exception statement from your version. */
37:
38:
39: package java.util;
40: import java.io.IOException;
41: import java.io.ObjectInputStream;
42: import java.io.ObjectOutputStream;
43: import java.io.Serializable;
44: import java.lang.reflect.Array;
45:
46: /**
47: * Linked list implementation of the List interface. In addition to the
48: * methods of the List interface, this class provides access to the first
49: * and last list elements in O(1) time for easy stack, queue, or double-ended
50: * queue (deque) creation. The list is doubly-linked, with traversal to a
51: * given index starting from the end closest to the element.<p>
52: *
53: * LinkedList is not synchronized, so if you need multi-threaded access,
54: * consider using:<br>
55: * <code>List l = Collections.synchronizedList(new LinkedList(...));</code>
56: * <p>
57: *
58: * The iterators are <i>fail-fast</i>, meaning that any structural
59: * modification, except for <code>remove()</code> called on the iterator
60: * itself, cause the iterator to throw a
61: * {@link ConcurrentModificationException} rather than exhibit
62: * non-deterministic behavior.
63: *
64: * @author Original author unknown
65: * @author Bryce McKinlay
66: * @author Eric Blake (ebb9@email.byu.edu)
67: * @author Tom Tromey (tromey@redhat.com)
68: * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
69: * @see List
70: * @see ArrayList
71: * @see Vector
72: * @see Collections#synchronizedList(List)
73: * @since 1.2
74: * @status Complete to 1.6
75: */
76: public class LinkedList<T> extends AbstractSequentialList<T>
77: implements List<T>, Deque<T>, Cloneable, Serializable
78: {
79: /**
80: * Compatible with JDK 1.2.
81: */
82: private static final long serialVersionUID = 876323262645176354L;
83:
84: /**
85: * The first element in the list.
86: */
87: transient Entry<T> first;
88:
89: /**
90: * The last element in the list.
91: */
92: transient Entry<T> last;
93:
94: /**
95: * The current length of the list.
96: */
97: transient int size = 0;
98:
99: /**
100: * Class to represent an entry in the list. Holds a single element.
101: */
102: private static final class Entry<T>
103: {
104: /** The element in the list. */
105: T data;
106:
107: /** The next list entry, null if this is last. */
108: Entry<T> next;
109:
110: /** The previous list entry, null if this is first. */
111: Entry<T> previous;
112:
113: /**
114: * Construct an entry.
115: * @param data the list element
116: */
117: Entry(T data)
118: {
119: this.data = data;
120: }
121: } // class Entry
122:
123: /**
124: * Obtain the Entry at a given position in a list. This method of course
125: * takes linear time, but it is intelligent enough to take the shorter of the
126: * paths to get to the Entry required. This implies that the first or last
127: * entry in the list is obtained in constant time, which is a very desirable
128: * property.
129: * For speed and flexibility, range checking is not done in this method:
130: * Incorrect values will be returned if (n < 0) or (n >= size).
131: *
132: * @param n the number of the entry to get
133: * @return the entry at position n
134: */
135: // Package visible for use in nested classes.
136: Entry<T> getEntry(int n)
137: {
138: Entry<T> e;
139: if (n < size / 2)
140: {
141: e = first;
142: // n less than size/2, iterate from start
143: while (n-- > 0)
144: e = e.next;
145: }
146: else
147: {
148: e = last;
149: // n greater than size/2, iterate from end
150: while (++n < size)
151: e = e.previous;
152: }
153: return e;
154: }
155:
156: /**
157: * Remove an entry from the list. This will adjust size and deal with
158: * `first' and `last' appropriatly.
159: *
160: * @param e the entry to remove
161: */
162: // Package visible for use in nested classes.
163: void removeEntry(Entry<T> e)
164: {
165: modCount++;
166: size--;
167: if (size == 0)
168: first = last = null;
169: else
170: {
171: if (e == first)
172: {
173: first = e.next;
174: e.next.previous = null;
175: }
176: else if (e == last)
177: {
178: last = e.previous;
179: e.previous.next = null;
180: }
181: else
182: {
183: e.next.previous = e.previous;
184: e.previous.next = e.next;
185: }
186: }
187: }
188:
189: /**
190: * Checks that the index is in the range of possible elements (inclusive).
191: *
192: * @param index the index to check
193: * @throws IndexOutOfBoundsException if index < 0 || index > size
194: */
195: private void checkBoundsInclusive(int index)
196: {
197: if (index < 0 || index > size)
198: throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
199: + size);
200: }
201:
202: /**
203: * Checks that the index is in the range of existing elements (exclusive).
204: *
205: * @param index the index to check
206: * @throws IndexOutOfBoundsException if index < 0 || index >= size
207: */
208: private void checkBoundsExclusive(int index)
209: {
210: if (index < 0 || index >= size)
211: throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
212: + size);
213: }
214:
215: /**
216: * Create an empty linked list.
217: */
218: public LinkedList()
219: {
220: }
221:
222: /**
223: * Create a linked list containing the elements, in order, of a given
224: * collection.
225: *
226: * @param c the collection to populate this list from
227: * @throws NullPointerException if c is null
228: */
229: public LinkedList(Collection<? extends T> c)
230: {
231: addAll(c);
232: }
233:
234: /**
235: * Returns the first element in the list.
236: *
237: * @return the first list element
238: * @throws NoSuchElementException if the list is empty
239: */
240: public T getFirst()
241: {
242: if (size == 0)
243: throw new NoSuchElementException();
244: return first.data;
245: }
246:
247: /**
248: * Returns the last element in the list.
249: *
250: * @return the last list element
251: * @throws NoSuchElementException if the list is empty
252: */
253: public T getLast()
254: {
255: if (size == 0)
256: throw new NoSuchElementException();
257: return last.data;
258: }
259:
260: /**
261: * Remove and return the first element in the list.
262: *
263: * @return the former first element in the list
264: * @throws NoSuchElementException if the list is empty
265: */
266: public T removeFirst()
267: {
268: if (size == 0)
269: throw new NoSuchElementException();
270: modCount++;
271: size--;
272: T r = first.data;
273:
274: if (first.next != null)
275: first.next.previous = null;
276: else
277: last = null;
278:
279: first = first.next;
280:
281: return r;
282: }
283:
284: /**
285: * Remove and return the last element in the list.
286: *
287: * @return the former last element in the list
288: * @throws NoSuchElementException if the list is empty
289: */
290: public T removeLast()
291: {
292: if (size == 0)
293: throw new NoSuchElementException();
294: modCount++;
295: size--;
296: T r = last.data;
297:
298: if (last.previous != null)
299: last.previous.next = null;
300: else
301: first = null;
302:
303: last = last.previous;
304:
305: return r;
306: }
307:
308: /**
309: * Insert an element at the first of the list.
310: *
311: * @param o the element to insert
312: */
313: public void addFirst(T o)
314: {
315: Entry<T> e = new Entry(o);
316:
317: modCount++;
318: if (size == 0)
319: first = last = e;
320: else
321: {
322: e.next = first;
323: first.previous = e;
324: first = e;
325: }
326: size++;
327: }
328:
329: /**
330: * Insert an element at the last of the list.
331: *
332: * @param o the element to insert
333: */
334: public void addLast(T o)
335: {
336: addLastEntry(new Entry<T>(o));
337: }
338:
339: /**
340: * Inserts an element at the end of the list.
341: *
342: * @param e the entry to add
343: */
344: private void addLastEntry(Entry<T> e)
345: {
346: modCount++;
347: if (size == 0)
348: first = last = e;
349: else
350: {
351: e.previous = last;
352: last.next = e;
353: last = e;
354: }
355: size++;
356: }
357:
358: /**
359: * Returns true if the list contains the given object. Comparison is done by
360: * <code>o == null ? e = null : o.equals(e)</code>.
361: *
362: * @param o the element to look for
363: * @return true if it is found
364: */
365: public boolean contains(Object o)
366: {
367: Entry<T> e = first;
368: while (e != null)
369: {
370: if (equals(o, e.data))
371: return true;
372: e = e.next;
373: }
374: return false;
375: }
376:
377: /**
378: * Returns the size of the list.
379: *
380: * @return the list size
381: */
382: public int size()
383: {
384: return size;
385: }
386:
387: /**
388: * Adds an element to the end of the list.
389: *
390: * @param o the entry to add
391: * @return true, as it always succeeds
392: */
393: public boolean add(T o)
394: {
395: addLastEntry(new Entry<T>(o));
396: return true;
397: }
398:
399: /**
400: * Removes the entry at the lowest index in the list that matches the given
401: * object, comparing by <code>o == null ? e = null : o.equals(e)</code>.
402: *
403: * @param o the object to remove
404: * @return true if an instance of the object was removed
405: */
406: public boolean remove(Object o)
407: {
408: Entry<T> e = first;
409: while (e != null)
410: {
411: if (equals(o, e.data))
412: {
413: removeEntry(e);
414: return true;
415: }
416: e = e.next;
417: }
418: return false;
419: }
420:
421: /**
422: * Append the elements of the collection in iteration order to the end of
423: * this list. If this list is modified externally (for example, if this
424: * list is the collection), behavior is unspecified.
425: *
426: * @param c the collection to append
427: * @return true if the list was modified
428: * @throws NullPointerException if c is null
429: */
430: public boolean addAll(Collection<? extends T> c)
431: {
432: return addAll(size, c);
433: }
434:
435: /**
436: * Insert the elements of the collection in iteration order at the given
437: * index of this list. If this list is modified externally (for example,
438: * if this list is the collection), behavior is unspecified.
439: *
440: * @param c the collection to append
441: * @return true if the list was modified
442: * @throws NullPointerException if c is null
443: * @throws IndexOutOfBoundsException if index < 0 || index > size()
444: */
445: public boolean addAll(int index, Collection<? extends T> c)
446: {
447: checkBoundsInclusive(index);
448: int csize = c.size();
449:
450: if (csize == 0)
451: return false;
452:
453: Iterator<? extends T> itr = c.iterator();
454:
455: // Get the entries just before and after index. If index is at the start
456: // of the list, BEFORE is null. If index is at the end of the list, AFTER
457: // is null. If the list is empty, both are null.
458: Entry<T> after = null;
459: Entry<T> before = null;
460: if (index != size)
461: {
462: after = getEntry(index);
463: before = after.previous;
464: }
465: else
466: before = last;
467:
468: // Create the first new entry. We do not yet set the link from `before'
469: // to the first entry, in order to deal with the case where (c == this).
470: // [Actually, we don't have to handle this case to fufill the
471: // contract for addAll(), but Sun's implementation appears to.]
472: Entry<T> e = new Entry<T>(itr.next());
473: e.previous = before;
474: Entry<T> prev = e;
475: Entry<T> firstNew = e;
476:
477: // Create and link all the remaining entries.
478: for (int pos = 1; pos < csize; pos++)
479: {
480: e = new Entry<T>(itr.next());
481: e.previous = prev;
482: prev.next = e;
483: prev = e;
484: }
485:
486: // Link the new chain of entries into the list.
487: modCount++;
488: size += csize;
489: prev.next = after;
490: if (after != null)
491: after.previous = e;
492: else
493: last = e;
494:
495: if (before != null)
496: before.next = firstNew;
497: else
498: first = firstNew;
499: return true;
500: }
501:
502: /**
503: * Remove all elements from this list.
504: */
505: public void clear()
506: {
507: if (size > 0)
508: {
509: modCount++;
510: first = null;
511: last = null;
512: size = 0;
513: }
514: }
515:
516: /**
517: * Return the element at index.
518: *
519: * @param index the place to look
520: * @return the element at index
521: * @throws IndexOutOfBoundsException if index < 0 || index >= size()
522: */
523: public T get(int index)
524: {
525: checkBoundsExclusive(index);
526: return getEntry(index).data;
527: }
528:
529: /**
530: * Replace the element at the given location in the list.
531: *
532: * @param index which index to change
533: * @param o the new element
534: * @return the prior element
535: * @throws IndexOutOfBoundsException if index < 0 || index >= size()
536: */
537: public T set(int index, T o)
538: {
539: checkBoundsExclusive(index);
540: Entry<T> e = getEntry(index);
541: T old = e.data;
542: e.data = o;
543: return old;
544: }
545:
546: /**
547: * Inserts an element in the given position in the list.
548: *
549: * @param index where to insert the element
550: * @param o the element to insert
551: * @throws IndexOutOfBoundsException if index < 0 || index > size()
552: */
553: public void add(int index, T o)
554: {
555: checkBoundsInclusive(index);
556: Entry<T> e = new Entry<T>(o);
557:
558: if (index < size)
559: {
560: modCount++;
561: Entry<T> after = getEntry(index);
562: e.next = after;
563: e.previous = after.previous;
564: if (after.previous == null)
565: first = e;
566: else
567: after.previous.next = e;
568: after.previous = e;
569: size++;
570: }
571: else
572: addLastEntry(e);
573: }
574:
575: /**
576: * Removes the element at the given position from the list.
577: *
578: * @param index the location of the element to remove
579: * @return the removed element
580: * @throws IndexOutOfBoundsException if index < 0 || index > size()
581: */
582: public T remove(int index)
583: {
584: checkBoundsExclusive(index);
585: Entry<T> e = getEntry(index);
586: removeEntry(e);
587: return e.data;
588: }
589:
590: /**
591: * Returns the first index where the element is located in the list, or -1.
592: *
593: * @param o the element to look for
594: * @return its position, or -1 if not found
595: */
596: public int indexOf(Object o)
597: {
598: int index = 0;
599: Entry<T> e = first;
600: while (e != null)
601: {
602: if (equals(o, e.data))
603: return index;
604: index++;
605: e = e.next;
606: }
607: return -1;
608: }
609:
610: /**
611: * Returns the last index where the element is located in the list, or -1.
612: *
613: * @param o the element to look for
614: * @return its position, or -1 if not found
615: */
616: public int lastIndexOf(Object o)
617: {
618: int index = size - 1;
619: Entry<T> e = last;
620: while (e != null)
621: {
622: if (equals(o, e.data))
623: return index;
624: index--;
625: e = e.previous;
626: }
627: return -1;
628: }
629:
630: /**
631: * Obtain a ListIterator over this list, starting at a given index. The
632: * ListIterator returned by this method supports the add, remove and set
633: * methods.
634: *
635: * @param index the index of the element to be returned by the first call to
636: * next(), or size() to be initially positioned at the end of the list
637: * @throws IndexOutOfBoundsException if index < 0 || index > size()
638: */
639: public ListIterator<T> listIterator(int index)
640: {
641: checkBoundsInclusive(index);
642: return new LinkedListItr<T>(index);
643: }
644:
645: /**
646: * Create a shallow copy of this LinkedList (the elements are not cloned).
647: *
648: * @return an object of the same class as this object, containing the
649: * same elements in the same order
650: */
651: public Object clone()
652: {
653: LinkedList<T> copy = null;
654: try
655: {
656: copy = (LinkedList<T>) super.clone();
657: }
658: catch (CloneNotSupportedException ex)
659: {
660: }
661: copy.clear();
662: copy.addAll(this);
663: return copy;
664: }
665:
666: /**
667: * Returns an array which contains the elements of the list in order.
668: *
669: * @return an array containing the list elements
670: */
671: public Object[] toArray()
672: {
673: Object[] array = new Object[size];
674: Entry<T> e = first;
675: for (int i = 0; i < size; i++)
676: {
677: array[i] = e.data;
678: e = e.next;
679: }
680: return array;
681: }
682:
683: /**
684: * Returns an Array whose component type is the runtime component type of
685: * the passed-in Array. The returned Array is populated with all of the
686: * elements in this LinkedList. If the passed-in Array is not large enough
687: * to store all of the elements in this List, a new Array will be created
688: * and returned; if the passed-in Array is <i>larger</i> than the size
689: * of this List, then size() index will be set to null.
690: *
691: * @param a the passed-in Array
692: * @return an array representation of this list
693: * @throws ArrayStoreException if the runtime type of a does not allow
694: * an element in this list
695: * @throws NullPointerException if a is null
696: */
697: public <S> S[] toArray(S[] a)
698: {
699: if (a.length < size)
700: a = (S[]) Array.newInstance(a.getClass().getComponentType(), size);
701: else if (a.length > size)
702: a[size] = null;
703: Entry<T> e = first;
704: for (int i = 0; i < size; i++)
705: {
706: a[i] = (S) e.data;
707: e = e.next;
708: }
709: return a;
710: }
711:
712: /**
713: * Adds the specified element to the end of the list.
714: *
715: * @param value the value to add.
716: * @return true.
717: * @since 1.5
718: */
719: public boolean offer(T value)
720: {
721: return add(value);
722: }
723:
724: /**
725: * Returns the first element of the list without removing
726: * it.
727: *
728: * @return the first element of the list.
729: * @throws NoSuchElementException if the list is empty.
730: * @since 1.5
731: */
732: public T element()
733: {
734: return getFirst();
735: }
736:
737: /**
738: * Returns the first element of the list without removing
739: * it.
740: *
741: * @return the first element of the list, or <code>null</code>
742: * if the list is empty.
743: * @since 1.5
744: */
745: public T peek()
746: {
747: if (size == 0)
748: return null;
749: return getFirst();
750: }
751:
752: /**
753: * Removes and returns the first element of the list.
754: *
755: * @return the first element of the list, or <code>null</code>
756: * if the list is empty.
757: * @since 1.5
758: */
759: public T poll()
760: {
761: if (size == 0)
762: return null;
763: return removeFirst();
764: }
765:
766: /**
767: * Removes and returns the first element of the list.
768: *
769: * @return the first element of the list.
770: * @throws NoSuchElementException if the list is empty.
771: * @since 1.5
772: */
773: public T remove()
774: {
775: return removeFirst();
776: }
777:
778: /**
779: * Serializes this object to the given stream.
780: *
781: * @param s the stream to write to
782: * @throws IOException if the underlying stream fails
783: * @serialData the size of the list (int), followed by all the elements
784: * (Object) in proper order
785: */
786: private void writeObject(ObjectOutputStream s) throws IOException
787: {
788: s.defaultWriteObject();
789: s.writeInt(size);
790: Entry<T> e = first;
791: while (e != null)
792: {
793: s.writeObject(e.data);
794: e = e.next;
795: }
796: }
797:
798: /**
799: * Deserializes this object from the given stream.
800: *
801: * @param s the stream to read from
802: * @throws ClassNotFoundException if the underlying stream fails
803: * @throws IOException if the underlying stream fails
804: * @serialData the size of the list (int), followed by all the elements
805: * (Object) in proper order
806: */
807: private void readObject(ObjectInputStream s)
808: throws IOException, ClassNotFoundException
809: {
810: s.defaultReadObject();
811: int i = s.readInt();
812: while (--i >= 0)
813: addLastEntry(new Entry<T>((T) s.readObject()));
814: }
815:
816: /**
817: * A ListIterator over the list. This class keeps track of its
818: * position in the list and the two list entries it is between.
819: *
820: * @author Original author unknown
821: * @author Eric Blake (ebb9@email.byu.edu)
822: */
823: private final class LinkedListItr<I>
824: implements ListIterator<I>
825: {
826: /** Number of modifications we know about. */
827: private int knownMod = modCount;
828:
829: /** Entry that will be returned by next(). */
830: private Entry<I> next;
831:
832: /** Entry that will be returned by previous(). */
833: private Entry<I> previous;
834:
835: /** Entry that will be affected by remove() or set(). */
836: private Entry<I> lastReturned;
837:
838: /** Index of `next'. */
839: private int position;
840:
841: /**
842: * Initialize the iterator.
843: *
844: * @param index the initial index
845: */
846: LinkedListItr(int index)
847: {
848: if (index == size)
849: {
850: next = null;
851: previous = (Entry<I>) last;
852: }
853: else
854: {
855: next = (Entry<I>) getEntry(index);
856: previous = next.previous;
857: }
858: position = index;
859: }
860:
861: /**
862: * Checks for iterator consistency.
863: *
864: * @throws ConcurrentModificationException if the list was modified
865: */
866: private void checkMod()
867: {
868: if (knownMod != modCount)
869: throw new ConcurrentModificationException();
870: }
871:
872: /**
873: * Returns the index of the next element.
874: *
875: * @return the next index
876: */
877: public int nextIndex()
878: {
879: return position;
880: }
881:
882: /**
883: * Returns the index of the previous element.
884: *
885: * @return the previous index
886: */
887: public int previousIndex()
888: {
889: return position - 1;
890: }
891:
892: /**
893: * Returns true if more elements exist via next.
894: *
895: * @return true if next will succeed
896: */
897: public boolean hasNext()
898: {
899: return (next != null);
900: }
901:
902: /**
903: * Returns true if more elements exist via previous.
904: *
905: * @return true if previous will succeed
906: */
907: public boolean hasPrevious()
908: {
909: return (previous != null);
910: }
911:
912: /**
913: * Returns the next element.
914: *
915: * @return the next element
916: * @throws ConcurrentModificationException if the list was modified
917: * @throws NoSuchElementException if there is no next
918: */
919: public I next()
920: {
921: checkMod();
922: if (next == null)
923: throw new NoSuchElementException();
924: position++;
925: lastReturned = previous = next;
926: next = lastReturned.next;
927: return lastReturned.data;
928: }
929:
930: /**
931: * Returns the previous element.
932: *
933: * @return the previous element
934: * @throws ConcurrentModificationException if the list was modified
935: * @throws NoSuchElementException if there is no previous
936: */
937: public I previous()
938: {
939: checkMod();
940: if (previous == null)
941: throw new NoSuchElementException();
942: position--;
943: lastReturned = next = previous;
944: previous = lastReturned.previous;
945: return lastReturned.data;
946: }
947:
948: /**
949: * Remove the most recently returned element from the list.
950: *
951: * @throws ConcurrentModificationException if the list was modified
952: * @throws IllegalStateException if there was no last element
953: */
954: public void remove()
955: {
956: checkMod();
957: if (lastReturned == null)
958: throw new IllegalStateException();
959:
960: // Adjust the position to before the removed element, if the element
961: // being removed is behind the cursor.
962: if (lastReturned == previous)
963: position--;
964:
965: next = lastReturned.next;
966: previous = lastReturned.previous;
967: removeEntry((Entry<T>) lastReturned);
968: knownMod++;
969:
970: lastReturned = null;
971: }
972:
973: /**
974: * Adds an element between the previous and next, and advance to the next.
975: *
976: * @param o the element to add
977: * @throws ConcurrentModificationException if the list was modified
978: */
979: public void add(I o)
980: {
981: checkMod();
982: modCount++;
983: knownMod++;
984: size++;
985: position++;
986: Entry<I> e = new Entry<I>(o);
987: e.previous = previous;
988: e.next = next;
989:
990: if (previous != null)
991: previous.next = e;
992: else
993: first = (Entry<T>) e;
994:
995: if (next != null)
996: next.previous = e;
997: else
998: last = (Entry<T>) e;
999:
1000: previous = e;
1001: lastReturned = null;
1002: }
1003:
1004: /**
1005: * Changes the contents of the element most recently returned.
1006: *
1007: * @param o the new element
1008: * @throws ConcurrentModificationException if the list was modified
1009: * @throws IllegalStateException if there was no last element
1010: */
1011: public void set(I o)
1012: {
1013: checkMod();
1014: if (lastReturned == null)
1015: throw new IllegalStateException();
1016: lastReturned.data = o;
1017: }
1018: } // class LinkedListItr
1019:
1020: /**
1021: * Obtain an Iterator over this list in reverse sequential order.
1022: *
1023: * @return an Iterator over the elements of the list in
1024: * reverse order.
1025: * @since 1.6
1026: */
1027: public Iterator<T> descendingIterator()
1028: {
1029: return new Iterator<T>()
1030: {
1031: /** Number of modifications we know about. */
1032: private int knownMod = modCount;
1033:
1034: /** Entry that will be returned by next(). */
1035: private Entry<T> next = last;
1036:
1037: /** Entry that will be affected by remove() or set(). */
1038: private Entry<T> lastReturned;
1039:
1040: /** Index of `next'. */
1041: private int position = size() - 1;
1042:
1043: // This will get inlined, since it is private.
1044: /**
1045: * Checks for modifications made to the list from
1046: * elsewhere while iteration is in progress.
1047: *
1048: * @throws ConcurrentModificationException if the
1049: * list has been modified elsewhere.
1050: */
1051: private void checkMod()
1052: {
1053: if (knownMod != modCount)
1054: throw new ConcurrentModificationException();
1055: }
1056:
1057: /**
1058: * Tests to see if there are any more objects to
1059: * return.
1060: *
1061: * @return true if the start of the list has not yet been
1062: * reached.
1063: */
1064: public boolean hasNext()
1065: {
1066: return next != null;
1067: }
1068:
1069: /**
1070: * Retrieves the next object from the list.
1071: *
1072: * @return The next object.
1073: * @throws NoSuchElementException if there are
1074: * no more objects to retrieve.
1075: * @throws ConcurrentModificationException if the
1076: * list has been modified elsewhere.
1077: */
1078: public T next()
1079: {
1080: checkMod();
1081: if (next == null)
1082: throw new NoSuchElementException();
1083: --position;
1084: lastReturned = next;
1085: next = lastReturned.previous;
1086: return lastReturned.data;
1087: }
1088:
1089: /**
1090: * Removes the last object retrieved by <code>next()</code>
1091: * from the list, if the list supports object removal.
1092: *
1093: * @throws ConcurrentModificationException if the list
1094: * has been modified elsewhere.
1095: * @throws IllegalStateException if the iterator is positioned
1096: * before the start of the list or the last object has already
1097: * been removed.
1098: */
1099: public void remove()
1100: {
1101: checkMod();
1102: if (lastReturned == null)
1103: throw new IllegalStateException();
1104: removeEntry(lastReturned);
1105: lastReturned = null;
1106: ++knownMod;
1107: }
1108: };
1109: }
1110:
1111: /**
1112: * Inserts the specified element at the front of the list.
1113: *
1114: * @param value the element to insert.
1115: * @return true.
1116: * @since 1.6
1117: */
1118: public boolean offerFirst(T value)
1119: {
1120: addFirst(value);
1121: return true;
1122: }
1123:
1124: /**
1125: * Inserts the specified element at the end of the list.
1126: *
1127: * @param value the element to insert.
1128: * @return true.
1129: * @since 1.6
1130: */
1131: public boolean offerLast(T value)
1132: {
1133: return add(value);
1134: }
1135:
1136: /**
1137: * Returns the first element of the list without removing
1138: * it.
1139: *
1140: * @return the first element of the list, or <code>null</code>
1141: * if the list is empty.
1142: * @since 1.6
1143: */
1144: public T peekFirst()
1145: {
1146: return peek();
1147: }
1148:
1149: /**
1150: * Returns the last element of the list without removing
1151: * it.
1152: *
1153: * @return the last element of the list, or <code>null</code>
1154: * if the list is empty.
1155: * @since 1.6
1156: */
1157: public T peekLast()
1158: {
1159: if (size == 0)
1160: return null;
1161: return getLast();
1162: }
1163:
1164: /**
1165: * Removes and returns the first element of the list.
1166: *
1167: * @return the first element of the list, or <code>null</code>
1168: * if the list is empty.
1169: * @since 1.6
1170: */
1171: public T pollFirst()
1172: {
1173: return poll();
1174: }
1175:
1176: /**
1177: * Removes and returns the last element of the list.
1178: *
1179: * @return the last element of the list, or <code>null</code>
1180: * if the list is empty.
1181: * @since 1.6
1182: */
1183: public T pollLast()
1184: {
1185: if (size == 0)
1186: return null;
1187: return removeLast();
1188: }
1189:
1190: /**
1191: * Pops an element from the stack by removing and returning
1192: * the first element in the list. This is equivalent to
1193: * calling {@link #removeFirst()}.
1194: *
1195: * @return the top of the stack, which is the first element
1196: * of the list.
1197: * @throws NoSuchElementException if the list is empty.
1198: * @since 1.6
1199: * @see #removeFirst()
1200: */
1201: public T pop()
1202: {
1203: return removeFirst();
1204: }
1205:
1206: /**
1207: * Pushes an element on to the stack by adding it to the
1208: * front of the list. This is equivalent to calling
1209: * {@link #addFirst(T)}.
1210: *
1211: * @param value the element to push on to the stack.
1212: * @throws NoSuchElementException if the list is empty.
1213: * @since 1.6
1214: * @see #addFirst(T)
1215: */
1216: public void push(T value)
1217: {
1218: addFirst(value);
1219: }
1220:
1221: /**
1222: * Removes the first occurrence of the specified element
1223: * from the list, when traversing the list from head to
1224: * tail. The list is unchanged if the element is not found.
1225: * This is equivalent to calling {@link #remove(Object)}.
1226: *
1227: * @param o the element to remove.
1228: * @return true if an instance of the object was removed.
1229: * @since 1.6
1230: */
1231: public boolean removeFirstOccurrence(Object o)
1232: {
1233: return remove(o);
1234: }
1235:
1236: /**
1237: * Removes the last occurrence of the specified element
1238: * from the list, when traversing the list from head to
1239: * tail. The list is unchanged if the element is not found.
1240: *
1241: * @param o the element to remove.
1242: * @return true if an instance of the object was removed.
1243: * @since 1.6
1244: */
1245: public boolean removeLastOccurrence(Object o)
1246: {
1247: Entry<T> e = last;
1248: while (e != null)
1249: {
1250: if (equals(o, e.data))
1251: {
1252: removeEntry(e);
1253: return true;
1254: }
1255: e = e.previous;
1256: }
1257: return false;
1258: }
1259:
1260: }