1. /*
  2. * @(#)LinkedList.java 1.27 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util;
  8. /**
  9. * Linked list implementation of the <tt>List</tt> interface. Implements all
  10. * optional list operations, and permits all elements (including
  11. * <tt>null</tt>). In addition to implementing the <tt>List</tt> interface,
  12. * the <tt>LinkedList</tt> class provides uniformly named methods to
  13. * <tt>get</tt>, <tt>remove</tt> and <tt>insert</tt> an element at the
  14. * beginning and end of the list. These operations allow linked lists to be
  15. * used as a stack, queue, or double-ended queue (deque).<p>
  16. *
  17. * All of the stack/queue/deque operations could be easily recast in terms of
  18. * the standard list operations. They're included here primarily for
  19. * convenience, though they may run slightly faster than the equivalent List
  20. * operations.<p>
  21. *
  22. * All of the operations perform as could be expected for a doubly-linked
  23. * list. Operations that index into the list will traverse the list from
  24. * the begining or the end, whichever is closer to the specified index.<p>
  25. *
  26. * <b>Note that this implementation is not synchronized.</b> If multiple
  27. * threads access a list concurrently, and at least one of the threads
  28. * modifies the list structurally, it <i>must</i> be synchronized
  29. * externally. (A structural modification is any operation that adds or
  30. * deletes one or more elements; merely setting the value of an element is not
  31. * a structural modification.) This is typically accomplished by
  32. * synchronizing on some object that naturally encapsulates the list. If no
  33. * such object exists, the list should be "wrapped" using the
  34. * Collections.synchronizedList method. This is best done at creation time,
  35. * to prevent accidental unsynchronized access to the list: <pre>
  36. * List list = Collections.synchronizedList(new LinkedList(...));
  37. * </pre><p>
  38. *
  39. * The iterators returned by the this class's <tt>iterator</tt> and
  40. * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is
  41. * structurally modified at any time after the iterator is created, in any way
  42. * except through the Iterator's own <tt>remove</tt> or <tt>add</tt> methods,
  43. * the iterator will throw a <tt>ConcurrentModificationException</tt>. Thus,
  44. * in the face of concurrent modification, the iterator fails quickly and
  45. * cleanly, rather than risking arbitrary, non-deterministic behavior at an
  46. * undetermined time in the future.
  47. *
  48. * @author Josh Bloch
  49. * @version 1.27 11/29/01
  50. * @see List
  51. * @see ArrayList
  52. * @see Vector
  53. * @see Collections#synchronizedList(List)
  54. * @since JDK1.2
  55. */
  56. public class LinkedList extends AbstractSequentialList
  57. implements List, Cloneable, java.io.Serializable
  58. {
  59. private transient Entry header = new Entry(null, null, null);
  60. private transient int size = 0;
  61. /**
  62. * Constructs an empty list.
  63. */
  64. public LinkedList() {
  65. header.next = header.previous = header;
  66. }
  67. /**
  68. * Constructs a list containing the elements of the specified
  69. * collection, in the order they are returned by the collection's
  70. * iterator.
  71. */
  72. public LinkedList(Collection c) {
  73. this();
  74. addAll(c);
  75. }
  76. /**
  77. * Returns the first element in this list.
  78. *
  79. * @return the first element in this list.
  80. */
  81. public Object getFirst() {
  82. if (size==0)
  83. throw new NoSuchElementException();
  84. return header.next.element;
  85. }
  86. /**
  87. * Returns the last element in this list.
  88. *
  89. * @return the last element in this list.
  90. * @throws NoSuchElementException if this list is empty.
  91. */
  92. public Object getLast() {
  93. if (size==0)
  94. throw new NoSuchElementException();
  95. return header.previous.element;
  96. }
  97. /**
  98. * Removes and returns the first element from this list.
  99. *
  100. * @return the first element from this list.
  101. * @throws NoSuchElementException if this list is empty.
  102. */
  103. public Object removeFirst() {
  104. Object first = header.next.element;
  105. remove(header.next);
  106. return first;
  107. }
  108. /**
  109. * Removes and returns the last element from this list.
  110. *
  111. * @return the last element from this list.
  112. * @throws NoSuchElementException if this list is empty.
  113. */
  114. public Object removeLast() {
  115. Object last = header.previous.element;
  116. remove(header.previous);
  117. return last;
  118. }
  119. /**
  120. * Inserts the given element at the beginning of this list.
  121. */
  122. public void addFirst(Object o) {
  123. addBefore(o, header.next);
  124. }
  125. /**
  126. * Appends the given element to the end of this list. (Identical in
  127. * function to the <tt>add</tt> method; included only for consistency.)
  128. */
  129. public void addLast(Object o) {
  130. addBefore(o, header);
  131. }
  132. /**
  133. * Returns <tt>true</tt> if this list contains the specified element.
  134. * More formally, returns <tt>true</tt> if and only if this list contains
  135. * at least one element <tt>e</tt> such that <tt>(o==null ? e==null
  136. * : o.equals(e))</tt>.
  137. *
  138. * @param o element whose presence in this list is to be tested.
  139. * @return <tt>true</tt> if this list contains the specified element.
  140. */
  141. public boolean contains(Object o) {
  142. return indexOf(o) != -1;
  143. }
  144. /**
  145. * Returns the number of elements in this list.
  146. *
  147. * @return the number of elements in this list.
  148. */
  149. public int size() {
  150. return size;
  151. }
  152. /**
  153. * Appends the specified element to the end of this list.
  154. *
  155. * @param o element to be appended to this list.
  156. * @return <tt>true</tt> (as per the general contract of
  157. * <tt>Collection.add</tt>).
  158. */
  159. public boolean add(Object o) {
  160. addBefore(o, header);
  161. return true;
  162. }
  163. /**
  164. * Removes the first occurrence of the specified element in this list. If
  165. * the list does not contain the element, it is unchanged. More formally,
  166. * removes the element with the lowest index <tt>i</tt> such that
  167. * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> (if such an
  168. * element exists).
  169. *
  170. * @param o element to be removed from this list, if present.
  171. * @return <tt>true</tt> if the list contained the specified element.
  172. */
  173. public boolean remove(Object o) {
  174. if (o==null) {
  175. for (Entry e = header.next; e != header; e = e.next) {
  176. if (e.element==null) {
  177. remove(e);
  178. return true;
  179. }
  180. }
  181. } else {
  182. for (Entry e = header.next; e != header; e = e.next) {
  183. if (o.equals(e.element)) {
  184. remove(e);
  185. return true;
  186. }
  187. }
  188. }
  189. return false;
  190. }
  191. /**
  192. * Appends all of the elements in the specified collection to the end of
  193. * this list, in the order that they are returned by the specified
  194. * collection's iterator. The behavior of this operation is undefined if
  195. * the specified collection is modified while the operation is in
  196. * progress. (This implies that the behavior of this call is undefined if
  197. * the specified Collection is this list, and this list is nonempty.)
  198. *
  199. * @param index index at which to insert first element
  200. * from the specified collection.
  201. * @param c elements to be inserted into this list.
  202. *
  203. * @throws IndexOutOfBoundsException if the specified index is out of
  204. * range (<tt>index < 0 || index > size()</tt>).
  205. */
  206. public boolean addAll(Collection c) {
  207. return addAll(size, c);
  208. }
  209. /**
  210. * Inserts all of the elements in the specified collection into this
  211. * list, starting at the specified position. Shifts the element
  212. * currently at that position (if any) and any subsequent elements to
  213. * the right (increases their indices). The new elements will appear
  214. * in the list in the order that they are returned by the
  215. * specified collection's iterator.
  216. *
  217. * @param index index at which to insert first element
  218. * from the specified collection.
  219. * @param c elements to be inserted into this list.
  220. * @throws IndexOutOfBoundsException if the specified index is out of
  221. * range (<tt>index < 0 || index > size()</tt>).
  222. */
  223. public boolean addAll(int index, Collection c) {
  224. int numNew = c.size();
  225. if (numNew==0)
  226. return false;
  227. modCount++;
  228. Entry successor = (index==size ? header : entry(index));
  229. Entry predecessor = successor.previous;
  230. Iterator it = c.iterator();
  231. for (int i=0; i<numNew; i++) {
  232. Entry e = new Entry(it.next(), successor, predecessor);
  233. predecessor.next = e;
  234. predecessor = e;
  235. }
  236. successor.previous = predecessor;
  237. size += numNew;
  238. return true;
  239. }
  240. /**
  241. * Removes all of the elements from this list.
  242. */
  243. public void clear() {
  244. modCount++;
  245. header.next = header.previous = header;
  246. size = 0;
  247. }
  248. // Positional Access Operations
  249. /**
  250. * Returns the element at the specified position in this list.
  251. *
  252. * @param index index of element to return.
  253. * @return the element at the specified position in this list.
  254. *
  255. * @throws IndexOutOfBoundsException if the specified index is is out of
  256. * range (<tt>index < 0 || index >= size()</tt>).
  257. */
  258. public Object get(int index) {
  259. return entry(index).element;
  260. }
  261. /**
  262. * Replaces the element at the specified position in this list with the
  263. * specified element.
  264. *
  265. * @param index index of element to replace.
  266. * @param element element to be stored at the specified position.
  267. * @return the element previously at the specified position.
  268. * @throws IndexOutOfBoundsException if the specified index is out of
  269. * range (<tt>index < 0 || index >= size()</tt>).
  270. */
  271. public Object set(int index, Object element) {
  272. Entry e = entry(index);
  273. Object oldVal = e.element;
  274. e.element = element;
  275. return oldVal;
  276. }
  277. /**
  278. * Inserts the specified element at the specified position in this list.
  279. * Shifts the element currently at that position (if any) and any
  280. * subsequent elements to the right (adds one to their indices).
  281. *
  282. * @param index index at which the specified element is to be inserted.
  283. * @param element element to be inserted.
  284. *
  285. * @throws IndexOutOfBoundsException if the specified index is out of
  286. * range (<tt>index < 0 || index > size()</tt>).
  287. */
  288. public void add(int index, Object element) {
  289. addBefore(element, (index==size ? header : entry(index)));
  290. }
  291. /**
  292. * Removes the element at the specified position in this list. Shifts any
  293. * subsequent elements to the left (subtracts one from their indices).
  294. * Returns the element that was removed from the list.
  295. *
  296. * @param index the index of the element to removed.
  297. * @return the element previously at the specified position.
  298. *
  299. * @throws IndexOutOfBoundsException if the specified index is out of
  300. * range (<tt>index < 0 || index >= size()</tt>).
  301. */
  302. public Object remove(int index) {
  303. Entry e = entry(index);
  304. remove(e);
  305. return e.element;
  306. }
  307. /**
  308. * Return the indexed entry.
  309. */
  310. private Entry entry(int index) {
  311. if (index < 0 || index >= size)
  312. throw new IndexOutOfBoundsException("Index: "+index+
  313. ", Size: "+size);
  314. Entry e = header;
  315. if (index < size2) {
  316. for (int i = 0; i <= index; i++)
  317. e = e.next;
  318. } else {
  319. for (int i = size; i > index; i--)
  320. e = e.previous;
  321. }
  322. return e;
  323. }
  324. // Search Operations
  325. /**
  326. * Returns the index in this list of the first occurrence of the
  327. * specified element, or -1 if the List does not contain this
  328. * element. More formally, returns the lowest index i such that
  329. * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, or -1 if
  330. * there is no such index.
  331. *
  332. * @param o element to search for.
  333. * @return the index in this list of the first occurrence of the
  334. * specified element, or -1 if the list does not contain this
  335. * element.
  336. */
  337. public int indexOf(Object o) {
  338. int index = 0;
  339. if (o==null) {
  340. for (Entry e = header.next; e != header; e = e.next) {
  341. if (e.element==null)
  342. return index;
  343. index++;
  344. }
  345. } else {
  346. for (Entry e = header.next; e != header; e = e.next) {
  347. if (o.equals(e.element))
  348. return index;
  349. index++;
  350. }
  351. }
  352. return -1;
  353. }
  354. /**
  355. * Returns the index in this list of the last occurrence of the
  356. * specified element, or -1 if the list does not contain this
  357. * element. More formally, returns the highest index i such that
  358. * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, or -1 if
  359. * there is no such index.
  360. *
  361. * @param o element to search for.
  362. * @return the index in this list of the last occurrence of the
  363. * specified element, or -1 if the list does not contain this
  364. * element.
  365. */
  366. public int lastIndexOf(Object o) {
  367. int index = size;
  368. if (o==null) {
  369. for (Entry e = header.previous; e != header; e = e.previous) {
  370. index--;
  371. if (e.element==null)
  372. return index;
  373. }
  374. } else {
  375. for (Entry e = header.previous; e != header; e = e.previous) {
  376. index--;
  377. if (o.equals(e.element))
  378. return index;
  379. }
  380. }
  381. return -1;
  382. }
  383. /**
  384. * Returns a list-iterator of the elements in this list (in proper
  385. * sequence), starting at the specified position in the list.
  386. * Obeys the general contract of <tt>List.listIterator(int)</tt>.<p>
  387. *
  388. * The list-iterator is <i>fail-fast</i>: if the list is structurally
  389. * modified at any time after the Iterator is created, in any way except
  390. * through the list-iterator's own <tt>remove</tt> or <tt>add</tt>
  391. * methods, the list-iterator will throw a
  392. * <tt>ConcurrentModificationException</tt>. Thus, in the face of
  393. * concurrent modification, the iterator fails quickly and cleanly, rather
  394. * than risking arbitrary, non-deterministic behavior at an undetermined
  395. * time in the future.
  396. *
  397. * @param index index of first element to be returned from the
  398. * list-iterator (by a call to <tt>next</tt>).
  399. * @return a ListIterator of the elements in this list (in proper
  400. * sequence), starting at the specified position in the list.
  401. * @throws IndexOutOfBoundsException if index is out of range
  402. * (<tt>index < 0 || index > size()</tt>).
  403. * @see List#listIterator(int)
  404. */
  405. public ListIterator listIterator(int index) {
  406. return new ListItr(index);
  407. }
  408. private class ListItr implements ListIterator {
  409. private Entry lastReturned = header;
  410. private Entry next;
  411. private int nextIndex;
  412. private int expectedModCount = modCount;
  413. ListItr(int index) {
  414. if (index < 0 || index > size)
  415. throw new IndexOutOfBoundsException("Index: "+index+
  416. ", Size: "+size);
  417. if (index < size2) {
  418. next = header.next;
  419. for (nextIndex=0; nextIndex<index; nextIndex++)
  420. next = next.next;
  421. } else {
  422. next = header;
  423. for (nextIndex=size; nextIndex>index; nextIndex--)
  424. next = next.previous;
  425. }
  426. }
  427. public boolean hasNext() {
  428. return nextIndex != size;
  429. }
  430. public Object next() {
  431. checkForComodification();
  432. if (nextIndex == size)
  433. throw new NoSuchElementException();
  434. lastReturned = next;
  435. next = next.next;
  436. nextIndex++;
  437. return lastReturned.element;
  438. }
  439. public boolean hasPrevious() {
  440. return nextIndex != 0;
  441. }
  442. public Object previous() {
  443. if (nextIndex == 0)
  444. throw new NoSuchElementException();
  445. lastReturned = next = next.previous;
  446. nextIndex--;
  447. checkForComodification();
  448. return lastReturned.element;
  449. }
  450. public int nextIndex() {
  451. return nextIndex;
  452. }
  453. public int previousIndex() {
  454. return nextIndex-1;
  455. }
  456. public void remove() {
  457. LinkedList.this.remove(lastReturned);
  458. if (next==lastReturned)
  459. next = lastReturned.next;
  460. else
  461. nextIndex--;
  462. lastReturned = header;
  463. expectedModCount++;
  464. }
  465. public void set(Object o) {
  466. if (lastReturned == header)
  467. throw new IllegalStateException();
  468. checkForComodification();
  469. lastReturned.element = o;
  470. }
  471. public void add(Object o) {
  472. checkForComodification();
  473. lastReturned = header;
  474. addBefore(o, next);
  475. nextIndex++;
  476. expectedModCount++;
  477. }
  478. final void checkForComodification() {
  479. if (modCount != expectedModCount)
  480. throw new ConcurrentModificationException();
  481. }
  482. }
  483. private static class Entry {
  484. Object element;
  485. Entry next;
  486. Entry previous;
  487. Entry(Object element, Entry next, Entry previous) {
  488. this.element = element;
  489. this.next = next;
  490. this.previous = previous;
  491. }
  492. }
  493. private Entry addBefore(Object o, Entry e) {
  494. Entry newEntry = new Entry(o, e, e.previous);
  495. newEntry.previous.next = newEntry;
  496. newEntry.next.previous = newEntry;
  497. size++;
  498. modCount++;
  499. return newEntry;
  500. }
  501. private void remove(Entry e) {
  502. if (e == header)
  503. throw new NoSuchElementException();
  504. e.previous.next = e.next;
  505. e.next.previous = e.previous;
  506. size--;
  507. modCount++;
  508. }
  509. /**
  510. * Returns a shallow copy of this <tt>LinkedList</tt>. (The elements
  511. * themselves are not cloned.)
  512. *
  513. * @return a shallow copy of this <tt>LinkedList</tt> instance.
  514. */
  515. public Object clone() {
  516. return new LinkedList(this);
  517. }
  518. /**
  519. * Returns an array containing all of the elements in this list
  520. * in the correct order.
  521. *
  522. * @return an array containing all of the elements in this list
  523. * in the correct order.
  524. */
  525. public Object[] toArray() {
  526. Object[] result = new Object[size];
  527. int i = 0;
  528. for (Entry e = header.next; e != header; e = e.next)
  529. result[i++] = e.element;
  530. return result;
  531. }
  532. /**
  533. * Returns an array containing all of the elements in this list in
  534. * the correct order. The runtime type of the returned array is that of
  535. * the specified array. If the list fits in the specified array, it
  536. * is returned therein. Otherwise, a new array is allocated with the
  537. * runtime type of the specified array and the size of this list.<p>
  538. *
  539. * If the list fits in the specified array with room to spare
  540. * (i.e., the array has more elements than the list),
  541. * the element in the array immediately following the end of the
  542. * collection is set to null. This is useful in determining the length
  543. * of the list <i>only</i> if the caller knows that the list
  544. * does not contain any null elements.
  545. *
  546. * @param a the array into which the elements of the list are to
  547. * be stored, if it is big enough; otherwise, a new array of the
  548. * same runtime type is allocated for this purpose.
  549. * @return an array containing the elements of the list.
  550. * @throws ArrayStoreException if the runtime type of a is not a
  551. * supertype of the runtime type of every element in this list.
  552. */
  553. public Object[] toArray(Object a[]) {
  554. if (a.length < size)
  555. a = (Object[])java.lang.reflect.Array.newInstance(
  556. a.getClass().getComponentType(), size);
  557. int i = 0;
  558. for (Entry e = header.next; e != header; e = e.next)
  559. a[i++] = e.element;
  560. if (a.length > size)
  561. a[size] = null;
  562. return a;
  563. }
  564. private static final long serialVersionUID = 876323262645176354L;
  565. /**
  566. * Save the state of this <tt>LinkedList</tt> instance to a stream (that
  567. * is, serialize it).
  568. *
  569. * @serialData The size of the list (the number of elements it
  570. * contains) is emitted (int), followed by all of its
  571. * elements (each an Object) in the proper order. */
  572. private synchronized void writeObject(java.io.ObjectOutputStream s)
  573. throws java.io.IOException {
  574. // Write out any hidden serialization magic
  575. s.defaultWriteObject();
  576. // Write out size
  577. s.writeInt(size);
  578. // Write out all elements in the proper order.
  579. for (Entry e = header.next; e != header; e = e.next)
  580. s.writeObject(e.element);
  581. }
  582. /**
  583. * Reconstitute this <tt>LinkedList</tt> instance from a stream (that is
  584. * deserialize it).
  585. */
  586. private synchronized void readObject(java.io.ObjectInputStream s)
  587. throws java.io.IOException, ClassNotFoundException {
  588. // Read in any hidden serialization magic
  589. s.defaultReadObject();
  590. // Read in size
  591. int size = s.readInt();
  592. // Initialize header
  593. header = new Entry(null, null, null);
  594. header.next = header.previous = header;
  595. // Read in all elements in the proper order.
  596. for (int i=0; i<size; i++)
  597. add(s.readObject());
  598. }
  599. }