LinkedList简介
LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作。
LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。
LinkedList构造函数 1 2 3 4 5 LinkedList() LinkedList(Collection<? extends E> collection)
LinkedList的API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 boolean add (E object) void add (int location, E object) boolean addAll (Collection<? extends E> collection) boolean addAll (int location, Collection<? extends E> collection) void addFirst (E object) void addLast (E object) void clear () Object clone () boolean contains (Object object) Iterator<E> descendingIterator () E element () E get (int location) E getFirst () E getLast () int indexOf (Object object) int lastIndexOf (Object object) ListIterator<E> listIterator (int location) boolean offer (E o) boolean offerFirst (E e) boolean offerLast (E e) E peek () E peekFirst () E peekLast () E poll () E pollFirst () E pollLast () E pop () void push (E e) E remove () E remove (int location) boolean remove (Object object) E removeFirst () boolean removeFirstOccurrence (Object o) E removeLast () boolean removeLastOccurrence (Object o) E set (int location, E object) int size () <T> T[] toArray (T[] contents) Object[] toArray ()
AbstractSequentialList简介 在介绍LinkedList的源码之前,先介绍一下AbstractSequentialList。毕竟,LinkedList是AbstractSequentialList的子类。
AbstractSequentialList 实现了get(int index)、set(int index, E element)、add(int index, E element)
和remove(int index)
这些函数。这些接口都是随机访问List的,LinkedList是双向链表;既然它继承于AbstractSequentialList
,就相当于已经实现了get(int index)
这些接口。
此外,我们若需要通过AbstractSequentialList自己实现一个列表,只需要扩展此类,并提供 listIterator() 和 size() 方法的实现即可。若要实现不可修改的列表,则需要实现列表迭代器的 hasNext、next、hasPrevious、previous 和 index 方法即可。
LinkedList数据结构 LinkedList的继承关系 1 2 3 4 5 java.lang.Object ↳ java.util.AbstractCollection<E> ↳ java.util.AbstractList<E> ↳ java.util.AbstractSequentialList<E> ↳ java.util.LinkedList<E>
1 2 3 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable {}
LinkedList与Collection关系图:
LinkedList的本质是双向链表。
LinkedList继承于AbstractSequentialList,并且实现了Dequeue接口。
LinkedList包含两个重要的成员:header 和 size。
header是双向链表的表头,它是双向链表节点所对应的类Entry的实例。Entry中包含成员变量: previous, next, element。其中,previous是该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值。 size是双向链表中节点的个数。
LinkedList源码解析(基于JDK1.6.0_45) 为了更了解LinkedList的原理,下面对LinkedList源码代码作出分析。
在阅读源码之前,我们先对LinkedList的整体实现进行大致说明:
LinkedList实际上是通过双向链表去实现的。既然是双向链表,那么它的顺序访问会非常高效,而随机访问效率比较低。
既然LinkedList是通过双向链表的,但是它也实现了List接口{也就是说,它实现了get(int location)、remove(int location)等“根据索引值来获取、删除节点的函数”}。
LinkedList是如何实现List的这些接口的,如何将“双向链表和索引值联系起来的”?
实际原理非常简单,它就是通过一个计数索引值来实现的。例如,当我们调用get(int location)时,首先会比较“location”和“双向链表长度的1/2”;若前者大,则从链表头开始往后查找,直到location位置;否则,从链表末尾开始先前查找,直到location位置。这就是“双线链表和索引值联系起来”的方法。
好了,接下来开始阅读源码(只要理解双向链表,那么LinkedList的源码很容易理解的)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 package java.util;public class LinkedList <E > extends AbstractSequentialList <E > implements List <E >, Deque <E >, Cloneable , java .io .Serializable { private transient Entry<E> header = new Entry<E>(null , null , null ); private transient int size = 0 ; public LinkedList () { header.next = header.previous = header; } public LinkedList (Collection<? extends E> c) { this (); addAll(c); } public E getFirst () { if (size==0 ) throw new NoSuchElementException(); return header.next.element; } public E getLast () { if (size==0 ) throw new NoSuchElementException(); return header.previous.element; } public E removeFirst () { return remove(header.next); } public E removeLast () { return remove(header.previous); } public void addFirst (E e) { addBefore(e, header.next); } public void addLast (E e) { addBefore(e, header); } public boolean contains (Object o) { return indexOf(o) != -1 ; } public int size () { return size; } public boolean add (E e) { addBefore(e, header); return true ; } public boolean remove (Object o) { if (o==null ) { for (Entry<E> e = header.next; e != header; e = e.next) { if (e.element==null ) { remove(e); return true ; } } } else { for (Entry<E> e = header.next; e != header; e = e.next) { if (o.equals(e.element)) { remove(e); return true ; } } } return false ; } public boolean addAll (Collection<? extends E> c) { return addAll(size, c); } public boolean addAll (int index, Collection<? extends E> c) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: " +index+ ", Size: " +size); Object[] a = c.toArray(); int numNew = a.length; if (numNew==0 ) return false ; modCount++; Entry<E> successor = (index==size ? header : entry(index)); Entry<E> predecessor = successor.previous; for (int i=0 ; i<numNew; i++) { Entry<E> e = new Entry<E>((E)a[i], successor, predecessor); predecessor.next = e; predecessor = e; } successor.previous = predecessor; size += numNew; return true ; } public void clear () { Entry<E> e = header.next; while (e != header) { Entry<E> next = e.next; e.next = e.previous = null ; e.element = null ; e = next; } header.next = header.previous = header; size = 0 ; modCount++; } public E get (int index) { return entry(index).element; } public E set (int index, E element) { Entry<E> e = entry(index); E oldVal = e.element; e.element = element; return oldVal; } public void add (int index, E element) { addBefore(element, (index==size ? header : entry(index))); } public E remove (int index) { return remove(entry(index)); } private Entry<E> entry (int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: " +index+ ", Size: " +size); Entry<E> e = header; if (index < (size >> 1 )) { for (int i = 0 ; i <= index; i++) e = e.next; } else { for (int i = size; i > index; i--) e = e.previous; } return e; } public int indexOf (Object o) { int index = 0 ; if (o==null ) { for (Entry e = header.next; e != header; e = e.next) { if (e.element==null ) return index; index++; } } else { for (Entry e = header.next; e != header; e = e.next) { if (o.equals(e.element)) return index; index++; } } return -1 ; } public int lastIndexOf (Object o) { int index = size; if (o==null ) { for (Entry e = header.previous; e != header; e = e.previous) { index--; if (e.element==null ) return index; } } else { for (Entry e = header.previous; e != header; e = e.previous) { index--; if (o.equals(e.element)) return index; } } return -1 ; } public E peek () { if (size==0 ) return null ; return getFirst(); } public E element () { return getFirst(); } public E poll () { if (size==0 ) return null ; return removeFirst(); } public boolean offer (E e) { return add(e); } public boolean offerFirst (E e) { addFirst(e); return true ; } public boolean offerLast (E e) { addLast(e); return true ; } public E peekFirst () { if (size==0 ) return null ; return getFirst(); } public E peekLast () { if (size==0 ) return null ; return getLast(); } public E pollFirst () { if (size==0 ) return null ; return removeFirst(); } public E pollLast () { if (size==0 ) return null ; return removeLast(); } public void push (E e) { addFirst(e); } public E pop () { return removeFirst(); } public boolean removeFirstOccurrence (Object o) { return remove(o); } public boolean removeLastOccurrence (Object o) { if (o==null ) { for (Entry<E> e = header.previous; e != header; e = e.previous) { if (e.element==null ) { remove(e); return true ; } } } else { for (Entry<E> e = header.previous; e != header; e = e.previous) { if (o.equals(e.element)) { remove(e); return true ; } } } return false ; } public ListIterator<E> listIterator (int index) { return new ListItr(index); } private class ListItr implements ListIterator <E > { private Entry<E> lastReturned = header; private Entry<E> next; private int nextIndex; private int expectedModCount = modCount; ListItr(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: " +index+ ", Size: " +size); if (index < (size >> 1 )) { next = header.next; for (nextIndex=0 ; nextIndex<index; nextIndex++) next = next.next; } else { next = header; for (nextIndex=size; nextIndex>index; nextIndex--) next = next.previous; } } public boolean hasNext () { return nextIndex != size; } public E next () { checkForComodification(); if (nextIndex == size) throw new NoSuchElementException(); lastReturned = next; next = next.next; nextIndex++; return lastReturned.element; } public boolean hasPrevious () { return nextIndex != 0 ; } public E previous () { if (nextIndex == 0 ) throw new NoSuchElementException(); lastReturned = next = next.previous; nextIndex--; checkForComodification(); return lastReturned.element; } public int nextIndex () { return nextIndex; } public int previousIndex () { return nextIndex-1 ; } public void remove () { checkForComodification(); Entry<E> lastNext = lastReturned.next; try { LinkedList.this .remove(lastReturned); } catch (NoSuchElementException e) { throw new IllegalStateException(); } if (next==lastReturned) next = lastNext; else nextIndex--; lastReturned = header; expectedModCount++; } public void set (E e) { if (lastReturned == header) throw new IllegalStateException(); checkForComodification(); lastReturned.element = e; } public void add (E e) { checkForComodification(); lastReturned = header; addBefore(e, next); nextIndex++; expectedModCount++; } final void checkForComodification () { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } private static class Entry <E > { E element; Entry<E> next; Entry<E> previous; Entry(E element, Entry<E> next, Entry<E> previous) { this .element = element; this .next = next; this .previous = previous; } } private Entry<E> addBefore (E e, Entry<E> entry) { Entry<E> newEntry = new Entry<E>(e, entry, entry.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; size++; modCount++; return newEntry; } private E remove (Entry<E> e) { if (e == header) throw new NoSuchElementException(); E result = e.element; e.previous.next = e.next; e.next.previous = e.previous; e.next = e.previous = null ; e.element = null ; size--; modCount++; return result; } public Iterator<E> descendingIterator () { return new DescendingIterator(); } private class DescendingIterator implements Iterator { final ListItr itr = new ListItr(size()); public boolean hasNext () { return itr.hasPrevious(); } public E next () { return itr.previous(); } public void remove () { itr.remove(); } } public Object[] toArray() { Object[] result = new Object[size]; int i = 0 ; for (Entry<E> e = header.next; e != header; e = e.next) result[i++] = e.element; return result; } public <T> T[] toArray(T[] a) { if (a.length < size) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); int i = 0 ; Object[] result = a; for (Entry<E> e = header.next; e != header; e = e.next) result[i++] = e.element; if (a.length > size) a[size] = null ; return a; } public Object clone () { LinkedList<E> clone = null ; try { clone = (LinkedList<E>) super .clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } clone.header = new Entry<E>(null , null , null ); clone.header.next = clone.header.previous = clone.header; clone.size = 0 ; clone.modCount = 0 ; for (Entry<E> e = header.next; e != header; e = e.next) clone.add(e.element); return clone; } private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException { s.defaultWriteObject(); s.writeInt(size); for (Entry e = header.next; e != header; e = e.next) s.writeObject(e.element); } private void readObject (java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); int size = s.readInt(); header = new Entry<E>(null , null , null ); header.next = header.previous = header; for (int i=0 ; i<size; i++) addBefore((E)s.readObject(), header); } }
总结:
1、LinkedList 实际上是通过双向链表去实现的。它包含一个非常重要的内部类:Entry。Entry是双向链表节点所对应的数据结构,它包括的属性有:当前节点所包含的值,上一个节点,下一个节点。
2、从LinkedList的实现方式中可以发现,它不存在LinkedList容量不足的问题。
3、LinkedList的克隆函数,即是将全部元素克隆到一个新的LinkedList对象中。
4、LinkedList实现java.io.Serializable。当写入到输出流时,先写入“容量”,再依次写入“每一个节点保护的值”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
5、由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)。
总结起来如下表格:
第一个元素
第一个元素
最后一个元素
最后一个元素
抛出异常
特殊值
抛出异常
特殊值
插入
addFirst(e)
offerFirst(e)
addLast(e)
offerLast(e)
移除
removeFirst()
pollFirst()
removeLast()
pollLast()
检查
getFirst()
peekFirst()
getLast()
peekLast()
6、LinkedList可以作为FIFO(先进先出)的队列,作为FIFO的队列时,下表的方法等价:
队列方法
等效方法
add(e)
addLast(e)
offer(e)
offerLast(e)
remove()
removeFirst()
poll()
pollFirst()
element()
getFirst()
peek()
peekFirst()
7、LinkedList可以作为LIFO(后进先出)的栈,作为LIFO的栈时,下表的方法等价:
栈方法
等效方法
push(e)
addFirst(e)
pop()
removeFirst()
peek()
peekFirst()
LinkedList遍历方式 LinkedList遍历方式
LinkedList支持多种遍历方式。建议不要采用随机访问的方式去遍历LinkedList,而采用逐个遍历的方式。
第一种,通过迭代器遍历。即通过Iterator去遍历。 1 2 for (Iterator iter = list.iterator(); iter.hasNext();) iter.next();
第二种,通过快速随机访问遍历LinkedList 1 2 3 4 int size = list.size();for (int i=0 ; i<size; i++) { list.get(i); }
第三种,通过另外一种for循环来遍历LinkedList 1 2 for (Integer integ:list) ;
通过pollFirst()来遍历LinkedList 1 2 while (list.pollFirst() != null ) ;
通过pollLast()来遍历LinkedList 1 2 while (list.pollLast() != null ) ;
通过removeFirst()来遍历LinkedList 1 2 3 4 5 try { while (list.removeFirst() != null ) ; } catch (NoSuchElementException e) { }
通过removeLast()来遍历LinkedList 1 2 3 4 5 try { while (list.removeLast() != null ) ; } catch (NoSuchElementException e) { }
测试这些遍历方式效率的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 import java.util.List;import java.util.Iterator;import java.util.LinkedList;import java.util.NoSuchElementException;public class LinkedListThruTest { public static void main (String[] args) { iteratorLinkedListThruIterator(getLinkedList()) ; iteratorLinkedListThruForeach(getLinkedList()) ; iteratorThroughFor2(getLinkedList()) ; iteratorThroughPollFirst(getLinkedList()) ; iteratorThroughPollLast(getLinkedList()) ; iteratorThroughRemoveFirst(getLinkedList()) ; iteratorThroughRemoveLast(getLinkedList()) ; } private static LinkedList getLinkedList () { LinkedList llist = new LinkedList(); for (int i=0 ; i<100000 ; i++) llist.addLast(i); return llist; } private static void iteratorLinkedListThruIterator (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); for (Iterator iter = list.iterator(); iter.hasNext();) iter.next(); long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorLinkedListThruIterator:" + interval+" ms" ); } private static void iteratorLinkedListThruForeach (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); int size = list.size(); for (int i=0 ; i<size; i++) { list.get(i); } long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorLinkedListThruForeach:" + interval+" ms" ); } private static void iteratorThroughFor2 (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); for (Integer integ:list) ; long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorThroughFor2:" + interval+" ms" ); } private static void iteratorThroughPollFirst (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); while (list.pollFirst() != null ) ; long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorThroughPollFirst:" + interval+" ms" ); } private static void iteratorThroughPollLast (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); while (list.pollLast() != null ) ; long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorThroughPollLast:" + interval+" ms" ); } private static void iteratorThroughRemoveFirst (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); try { while (list.removeFirst() != null ) ; } catch (NoSuchElementException e) { } long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorThroughRemoveFirst:" + interval+" ms" ); } private static void iteratorThroughRemoveLast (LinkedList<Integer> list) { if (list == null ) return ; long start = System.currentTimeMillis(); try { while (list.removeLast() != null ) ; } catch (NoSuchElementException e) { } long end = System.currentTimeMillis(); long interval = end - start; System.out.println("iteratorThroughRemoveLast:" + interval+" ms" ); } }
执行结果:
1 2 3 4 5 6 7 iteratorLinkedListThruIterator:8 ms iteratorLinkedListThruForeach:3724 ms iteratorThroughFor2:5 ms iteratorThroughPollFirst:8 ms iteratorThroughPollLast:6 ms iteratorThroughRemoveFirst:2 ms iteratorThroughRemoveLast:2 ms
由此可见,遍历LinkedList时,使用removeFist()或removeLast()效率最高。但用它们遍历时,会删除原始数据;若单纯只读取,而不删除,应该使用第3种 (增强 for循环) 遍历方式。 无论如何,千万不要通过随机访问去遍历LinkedList!
LinkedList示例 下面通过一个示例来学习如何使用LinkedList的常用API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 import java.util.List;import java.util.Iterator;import java.util.LinkedList;import java.util.NoSuchElementException;public class LinkedListTest { public static void main (String[] args) { testLinkedListAPIs() ; useLinkedListAsLIFO(); useLinkedListAsFIFO(); } private static void testLinkedListAPIs () { String val = null ; LinkedList llist = new LinkedList(); llist.add("1" ); llist.add("2" ); llist.add("3" ); llist.add(1 , "4" ); System.out.println("\nTest \"addFirst(), removeFirst(), getFirst()\"" ); llist.addFirst("10" ); System.out.println("llist:" +llist); System.out.println("llist.removeFirst():" +llist.removeFirst()); System.out.println("llist:" +llist); System.out.println("llist.getFirst():" +llist.getFirst()); System.out.println("\nTest \"offerFirst(), pollFirst(), peekFirst()\"" ); llist.offerFirst("10" ); System.out.println("llist:" +llist); System.out.println("llist.pollFirst():" +llist.pollFirst()); System.out.println("llist:" +llist); System.out.println("llist.peekFirst():" +llist.peekFirst()); System.out.println("\nTest \"addLast(), removeLast(), getLast()\"" ); llist.addLast("20" ); System.out.println("llist:" +llist); System.out.println("llist.removeLast():" +llist.removeLast()); System.out.println("llist:" +llist); System.out.println("llist.getLast():" +llist.getLast()); System.out.println("\nTest \"offerLast(), pollLast(), peekLast()\"" ); llist.offerLast("20" ); System.out.println("llist:" +llist); System.out.println("llist.pollLast():" +llist.pollLast()); System.out.println("llist:" +llist); System.out.println("llist.peekLast():" +llist.peekLast()); llist.set(2 , "300" ); System.out.println("\nget(3):" +llist.get(2 )); String[] arr = (String[])llist.toArray(new String[0 ]); for (String str:arr) System.out.println("str:" +str); System.out.println("size:" +llist.size()); llist.clear(); System.out.println("isEmpty():" +llist.isEmpty()+"\n" ); } private static void useLinkedListAsLIFO () { System.out.println("\nuseLinkedListAsLIFO" ); LinkedList stack = new LinkedList(); stack.push("1" ); stack.push("2" ); stack.push("3" ); stack.push("4" ); System.out.println("stack:" +stack); System.out.println("stack.pop():" +stack.pop()); System.out.println("stack.peek():" +stack.peek()); System.out.println("stack:" +stack); } private static void useLinkedListAsFIFO () { System.out.println("\nuseLinkedListAsFIFO" ); LinkedList queue = new LinkedList(); queue.add("10" ); queue.add("20" ); queue.add("30" ); queue.add("40" ); System.out.println("queue:" +queue); System.out.println("queue.remove():" +queue.remove()); System.out.println("queue.element():" +queue.element()); System.out.println("queue:" +queue); } }
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 Test "addFirst(), removeFirst(), getFirst()" llist:[10 , 1 , 4 , 2 , 3 ] llist.removeFirst():10 llist:[1 , 4 , 2 , 3 ] llist.getFirst():1 Test "offerFirst(), pollFirst(), peekFirst()" llist:[10 , 1 , 4 , 2 , 3 ] llist.pollFirst():10 llist:[1 , 4 , 2 , 3 ] llist.peekFirst():1 Test "addLast(), removeLast(), getLast()" llist:[1 , 4 , 2 , 3 , 20 ] llist.removeLast():20 llist:[1 , 4 , 2 , 3 ] llist.getLast():3 Test "offerLast(), pollLast(), peekLast()" llist:[1 , 4 , 2 , 3 , 20 ] llist.pollLast():20 llist:[1 , 4 , 2 , 3 ] llist.peekLast():3 get(3 ):300 str:1 str:4 str:300 str:3 size:4 isEmpty():true useLinkedListAsLIFO stack:[4 , 3 , 2 , 1 ] stack.pop():4 stack.peek():3 stack:[3 , 2 , 1 ] useLinkedListAsFIFO queue:[10 , 20 , 30 , 40 ] queue.remove():10 queue.element():20 queue:[20 , 30 , 40 ]