关闭

【源代码】java.util.LinkedList

262人阅读 评论(0) 收藏 举报
分类:

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:   }


接下来,LinkedList中定义了两个构造函数。分别针对无参情况和参数为一个容器类型的情况。

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: }






0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7152次
    • 积分:262
    • 等级:
    • 排名:千里之外
    • 原创:19篇
    • 转载:0篇
    • 译文:1篇
    • 评论:0条