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