-
Notifications
You must be signed in to change notification settings - Fork 610
/
LinkedList.java
1269 lines (1158 loc) · 40.1 KB
/
LinkedList.java
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
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package java.util;
import java.util.function.Consumer;
/**
* LinkedList是List和Deque接口的双向链表的实现。实现了所有可选List操作,并允许包括null值。
* LinkedList既然是通过双向链表去实现的,那么它可以被当作堆栈、队列或双端队列进行操作。并且其顺序访问非常高效,而随机访问效率比较低。
* 内部方法,注释会描述为节点的操作(如删除第一个节点),公开的方法会描述为元素的操作(如删除第一个元素)
* 注意,此实现不是同步的。 如果多个线程同时访问一个LinkedList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。
* LinkedList不是线程安全的,如果在多线程中使用(修改),需要在外部作同步处理。
* 这通常是通过同步那些用来封装列表的对象来实现的。
* 但如果没有这样的对象存在,则该列表需要运用{@link Collections#synchronizedList Collections.synchronizedList}来进行“包装”,该方法最好是在创建列表对象时完成,为了避免对列表进行突发的非同步操作。
*/
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
/**
* 元素数量
*/
transient int size = 0;
/**
* 首结点引用
*/
transient Node<E> first;
/**
* 尾节点引用
*/
transient Node<E> last;
/**
* 无参构造方法
*/
public LinkedList() {
}
/**
* 通过一个集合初始化LinkedList,元素顺序有这个集合的迭代器返回顺序决定
*
* @param c 其元素将被放入此列表中的集合
* @throws NullPointerException 如果指定的集合是空的
*/
public LinkedList(Collection<? extends E> c) {
// 调用无参构造函数
this();
// 添加集合中所有的元素
addAll(c);
}
/**
* 头插入,即将节点值为e的节点设置为链表首节点,内部使用
*/
private void linkFirst(E e) {
//获取当前首结点引用
final Node<E> f = first;
//构建一个prev值为null,节点值为e,next值为f的新节点newNode
final Node<E> newNode = new Node<>(null, e, f);
//将newNode作为首节点
first = newNode;
//如果原首节点为null,即原链表为null,则链表尾节点也设置为newNode
if (f == null)
last = newNode;
else //否则,原首节点的prev设置为newNode
f.prev = newNode;
size++; //长度+1
modCount++; //修改次数+1
}
/**
* 尾插入,即将节点值为e的节点设置为链表的尾节点
*/
void linkLast(E e) {
// 获取当前尾结点引用
final Node<E> l = last;
//构建一个prev值为l,节点值为e,next值为null的新节点newNode
final Node<E> newNode = new Node<>(l, e, null);
//将newNode作为尾节点
last = newNode;
//如果原尾节点为null,即原链表为null,则链表首节点也设置为newNode
if (l == null)
first = newNode;
else //否则,原尾节点的next设置为newNode
l.next = newNode;
size++;
modCount++;
}
/**
* 中间插入,在非空节点succ之前插入节点值e
*/
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
//构建一个prev值为succ.prev,节点值为e,next值为succ的新节点newNode
final Node<E> newNode = new Node<>(pred, e, succ);
//设置newNode为succ的前节点
succ.prev = newNode;
//如果succ.prev为null,即如果succ为首节点,则将newNode设置为首节点
if (pred == null)
first = newNode;
else //如果succ不是首节点
pred.next = newNode;
size++;
modCount++;
}
/**
* 删除首结点,返回存储的元素,内部使用
*/
private E unlinkFirst(Node<E> f) {
// 获取首结点存储的元素
final E element = f.item;
// 获取首结点的后继结点
final Node<E> next = f.next;
// 删除首结点
f.item = null;
f.next = null; //便于垃圾回收期清理
// 原来首结点的后继结点设为首结点
first = next;
// 如果原来首结点的后继结点为空,则尾结点设为null
// 否则,原来首结点的后继结点的前驱结点设为null
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
// 返回原来首结点存储的元素
return element;
}
/**
* 删除尾结点,返回存储的元素,内部使用
*/
private E unlinkLast(Node<E> l) {
// 获取尾结点存储的元素
final E element = l.item;
// 获取尾结点的前驱结点
final Node<E> prev = l.prev;
// 删除尾结点
l.item = null;
l.prev = null; // help GC
// 原来尾结点的前驱结点设为尾结点
last = prev;
// 如果原来尾结点的前驱结点为空,则首结点设为null
// 否则,原来尾结点的前驱结点的后继结点设为null
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
// 返回原来尾结点存储的元素
return element;
}
/**
* 删除指定非空结点,返回存储的元素
*/
E unlink(Node<E> x) {
// 获取指定非空结点存储的元素
final E element = x.item;
// 获取指定非空结点的后继结点
final Node<E> next = x.next;
// 获取指定非空结点的前驱结点
final Node<E> prev = x.prev;
/**
* 如果指定非空结点的前驱结点为空,则指定非空结点的后继结点设为首结点
* 否则,指定非空结点的后继结点设为指定非空结点的前驱结点的后继结点,
* 指定非空结点的前驱结点设为null
*/
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
/**
* 如果指定非空结点的后继结点为空,则指定非空结点的前驱结点设为尾结点
* 否则,指定非空结点的前驱结点设为指定非空结点的后继结点的前驱结点,
* 指定非空结点的后继结点设为null
*/
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
// 指定非空结点存储的元素设为null
x.item = null;
size--;
modCount++;
// 返回指定非空结点存储的元素
return element;
}
/**
* 获取首结点存储的元素
*
* @return 首结点存储的元素
* @throws NoSuchElementException 如果链表为空
*/
public E getFirst() {
// 获取首结点引用
final Node<E> f = first;
// 如果首结点为空,则抛出无该元素异常
if (f == null)
throw new NoSuchElementException();
// 返回首结点存储的元素
return f.item;
}
/**
* 获取尾结点存储的元素
*
* @return 尾结点存储的元素
* @throws NoSuchElementException 如果链表为空
*/
public E getLast() {
// 获取尾结点引用
final Node<E> l = last;
// 如果尾结点为空,则抛出无该元素异常
if (l == null)
throw new NoSuchElementException();
// 返回尾结点存储的元素
return l.item;
}
/**
* 删除首结点,返回存储的元素
*
* @return 首结点存储的元素
* @throws NoSuchElementException 如果链表为空
*/
public E removeFirst() {
// 获取首结点引用
final Node<E> f = first;
// 如果首结点为空,则抛出无该元素异常
if (f == null)
throw new NoSuchElementException();
// 删除首结点,返回存储的元素
return unlinkFirst(f);
}
/**
* 删除尾结点,返回存储的元素
*
* @return 尾结点存储的元素
* @throws NoSuchElementException 如果链表为空
*/
public E removeLast() {
// 获取尾结点引用
final Node<E> l = last;
// 如果尾结点为空,则抛出无该元素异常
if (l == null)
throw new NoSuchElementException();
// 删除尾结点,返回存储的元素
return unlinkLast(l);
}
/**
* 头部插入指定元素
*
* @param e 要添加的元素
*/
public void addFirst(E e) {
// 通过头插法来插入指定元素
linkFirst(e);
}
/**
* 尾部插入指定元素,该方法等价于add()
*
* @param e the element to add
*/
public void addLast(E e) {
linkLast(e);
}
/**
* 判断是否包含指定元素
*
* @param o 判断链表是否包含的元素
* @return {@code true} 如果链表包含指定的元素
*/
public boolean contains(Object o) {
//返回指定元素的索引位置,不存在就返回-1,然后比较返回bool值
return indexOf(o) != -1;
}
/**
* 获取元素数量
*
* @return 元素数量
*/
public int size() {
return size;
}
/**
* 插入指定元素,返回操作结果,默认添加到末尾作为最后一个元素
*
* @param e 要添加到此链表中的元素
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
// 通过尾插法来插入指定元素
linkLast(e);
return true;
}
/**
* 删除指定元素,默认从first节点开始,删除第一次出现的那个元素
*
* @param o 要从该列表中删除的元素(如果存在)
* @return {@code true} 如果这个列表包含指定的元素
*/
public boolean remove(Object o) {
//会根据是否为null分开处理。若值不是null,会用到对象的equals()方法
if (o == null) {
// 遍历链表,查找到指定元素后删除该结点,返回true
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
// 查找失败
return false;
}
/**
* 将集合插入到链表尾部,即开始索引位置为size
*
* @param c 包含要添加到此链表中的元素的集合
* @return {@code true} 如果该链表因添加而改变
* @throws NullPointerException 如果指定的集合是空的
*/
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
/**
* 将集合从指定位置开始插入
*
* @param index 在哪个索引处前插入指定集合中的第一个元素
* @param c 包含要添加到此链表中的元素的集合
* @return {@code true} 如果该链表因添加而改变
* @throws IndexOutOfBoundsException {@inheritDoc}
* @throws NullPointerException 如果指定的集合是空的
*/
public boolean addAll(int index, Collection<? extends E> c) {
//检查索引是否正确(0<=index<=size)
checkPositionIndex(index);
//得到元素数组
Object[] a = c.toArray();
//得到元素个数
int numNew = a.length;
//若没有元素要添加,直接返回false
if (numNew == 0)
return false;
//succ指向当前需要插入节点的位置,pred指向其前一个节点
Node<E> pred, succ;
//如果是在末尾开始添加,当前节点后一个节点初始化为null,前一个节点为尾节点
if (index == size) {
succ = null;
pred = last;
} else { //如果不是从末尾开始添加,当前位置的节点为指定位置的节点,前一个节点为要添加的节点的前一个节点
succ = node(index);
pred = succ.prev;
}
//遍历数组并添加到列表中
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
//将元素值e,前继节点pred“封装”为一个新节点newNode
Node<E> newNode = new Node<>(pred, e, null);
//如果原链表为null,则新插入的节点作为链表首节点
if (pred == null)
first = newNode;
else
pred.next = newNode; //如果存在前节点,前节点会向后指向新加的节点
pred = newNode; //pred指针向后移动,指向下一个需插入节点位置的前一个节点
}
//如果是从最后开始添加的,则最后添加的节点成为尾节点
if (succ == null) {
last = pred;
} else {
pred.next = succ; //如果不是从最后开始添加的,则最后添加的节点向后指向之前得到的后续第一个节点
succ.prev = pred; //当前,后续的第一个节点也应改为向前指向最后一个添加的节点
}
size += numNew;
modCount++;
return true;
}
/**
* 删除所有元素
*/
public void clear() {
//遍历链表,删除所有结点,方便gc回收垃圾
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
// 首尾结点置空
first = last = null;
// 元素数量置0
size = 0;
modCount++;
}
// 位置访问操作
/**
* 获取指定位置的元素
*
* @param index 要返回的元素的索引
* @return 该链表中指定位置的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
// 判断指定位置是否合法
checkElementIndex(index);
// 返回指定位置的元素
return node(index).item;
}
/**
* 修改指定位置的元素,返回之前元素
*
* @param index 要替换的元素的索引
* @param element 要存储在指定位置的元素
* @return 之前在指定位置的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
// 判断指定位置是否合法
checkElementIndex(index);
// 获取指定位置的结点
Node<E> x = node(index);
// 获取该结点存储的元素
E oldVal = x.item;
// 修改该结点存储的元素
x.item = element;
// 返回该结点存储的之前的元素
return oldVal;
}
/**
* 在指定位置前插入指定元素
*
* @param index 指定元素将被插入的索引
* @param element 要插入的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
// 判断指定位置是否合法
checkPositionIndex(index);
// 如果指定位置在尾部,则通过尾插法来插入指定元素
if (index == size)
linkLast(element);
else //如果指定位置不是尾部,则添加到指定位置前
linkBefore(element, node(index));
}
/**
* 删除指定位置的元素,返回之前元素
*
* @param index 要删除的元素的索引
* @return 之前在指定位置的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
// 判断指定位置是否合法
checkElementIndex(index);
// 删除指定位置的结点,返回之前元素
return unlink(node(index));
}
/**
* 判断指定位置是否合法
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
/**
* 判断迭代器遍历时或插入元素时指定位置是否合法
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
/**
* 获取越界异常信息
*/
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + size;
}
/**
* 判断指定位置是否合法
*
* @param index
*/
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 判断指定位置是否合法
*
* @param index
*/
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 获取指定下标的结点,index从0开始
*/
Node<E> node(int index) {
// 如果指定下标<一半元素数量,则从首结点开始遍历
// 否则,从尾结点开始遍历
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
// 查询操作
/**
* 获取顺序下首次出现指定元素的位置
* 如果返回结果是-1,则表示不存在该元素
*
* @param o 要查找的元素
* @return the index of the first occurrence of the specified element in
* this list, or -1 if this list does not contain the element
*/
public int indexOf(Object o) {
int index = 0;
if (o == null) {
// 遍历链表,顺序查找指定元素
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
/**
* 获取逆序下首次出现指定元素的位置
* 如果返回结果是-1,则表示不存在该元素
*
* @param o 要查找的元素
* @return the index of the last occurrence of the specified element in
* this list, or -1 if this list does not contain the element
*/
public int lastIndexOf(Object o) {
int index = size;
if (o == null) {
// 遍历链表,逆序查找指定元素
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)
return index;
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))
return index;
}
}
return -1;
}
// 队列操作
/**
* 出队(从前端),获得第一个元素,不存在会返回null,不会删除元素(节点)
* 获取首元素
*
* @return the head of this list, or {@code null} 如果链表为空
* @since 1.5
*/
public E peek() {
final Node<E> f = first;
// 如果首结点为空,则返回null
// 否则,返回首结点存储的元素
return (f == null) ? null : f.item;
}
/**
* 出队(从前端),不删除元素,若为null会抛出异常而不是返回null
* 获取首元素
*
* @return the head of this list
* @throws NoSuchElementException 如果链表为空
* @since 1.5
*/
public E element() {
// 返回首结点存储的元素
return getFirst();
}
/**
* 出队(从前端),如果不存在会返回null,存在的话会返回值并移除这个元素(节点)
* 获取并删除首元素
*
* @return the head of this list, or {@code null} 如果链表为空
* @since 1.5
*/
public E poll() {
// 获取首结点引用
final Node<E> f = first;
// 如果首结点为空,则返回null
// 否则,删除首结点,返回首结点存储的元素
return (f == null) ? null : unlinkFirst(f);
}
/**
* 出队(从前端),如果不存在会抛出异常而不是返回null,存在的话会返回值并移除这个元素(节点)
* 获取并删除首元素
*
* @return the head of this list
* @throws NoSuchElementException 如果链表为空
* @since 1.5
*/
public E remove() {
// 删除首结点,返回首结点存储的元素
return removeFirst();
}
/**
* 入队(从后端),始终返回true
*
* @param e the element to add
* @return {@code true} (as specified by {@link Queue#offer})
* @since 1.5
*/
public boolean offer(E e) {
// 通过尾插法插入指定元素,返回操作结果
return add(e);
}
// 双端队列操作
/**
* 入队(从前端),始终返回true
*
* @param e 要插入的元素
* @return {@code true} (as specified by {@link Deque#offerFirst})
* @since 1.6
*/
public boolean offerFirst(E e) {
// 通过尾插法来插入指定元素
addFirst(e);
return true;
}
/**
* 入队(从后端),始终返回true
*
* @param e 要插入的元素
* @return {@code true} (as specified by {@link Deque#offerLast})
* @since 1.6
*/
public boolean offerLast(E e) {
// 通过尾插法来插入指定元素
addLast(e);
return true;
}
/**
* 出队(从后端),获得最后一个元素,不存在会返回null,不会删除元素(节点)
*
* @return the first element of this list, or {@code null}
* 如果链表为空
* @since 1.6
*/
public E peekFirst() {
// 获取首结点引用
final Node<E> f = first;
// 如果首结点为空,则返回null
// 否则,返回首结点存储的元素
return (f == null) ? null : f.item;
}
/**
* 出队(从后端),获得最后一个元素,不存在会返回null,不会删除元素(节点)
*
* @return the last element of this list, or {@code null}
* 如果链表为空
* @since 1.6
*/
public E peekLast() {
// 获取尾结点引用
final Node<E> l = last;
// 如果尾结点为空,则返回null
// 否则,返回尾结点存储的元素
return (l == null) ? null : l.item;
}
/**
* 出队(从前端),获得第一个元素,不存在会返回null,会删除元素(节点)
*
* @return the first element of this list, or {@code null} if
* this list is empty
* @since 1.6
*/
public E pollFirst() {
// 获取首结点引用
final Node<E> f = first;
// 如果首结点为空,则返回null
// 否则,删除首结点,返回首结点存储的元素
return (f == null) ? null : unlinkFirst(f);
}
/**
* 出队(从后端),获得最后一个元素,不存在会返回null,会删除元素(节点)
*
* @return the last element of this list, or {@code null} if
* this list is empty
* @since 1.6
*/
public E pollLast() {
// 获取尾结点引用
final Node<E> l = last;
// 如果尾结点为空,则返回null
// 否则,删除尾结点,返回尾结点存储的元素
return (l == null) ? null : unlinkLast(l);
}
/**
* 入栈,从前面添加
*
* @param e the element to push
* @since 1.6
*/
public void push(E e) {
// 通过头插法来插入指定元素
addFirst(e);
}
/**
* 出栈,返回栈顶元素,从前面移除(会删除)
*
* @return the element at the front of this list (which is the top
* of the stack represented by this list)
* @throws NoSuchElementException 如果链表为空
* @since 1.6
*/
public E pop() {
// 删除首结点,返回首结点存储的元素
return removeFirst();
}
/**
* 删除顺序下首次出现的指定元素,返回操作结果
*
* @param o 要从该列表中删除的元素(如果存在)
* @return {@code true} 如果链表包含指定的元素
* @since 1.6
*/
public boolean removeFirstOccurrence(Object o) {
// 删除顺序下首次出现的指定元素对应的结点,返回操作结果
return remove(o);
}
/**
* 删除逆序下首次出现的指定元素,返回操作结果
*
* @param o 要从该列表中删除的元素(如果存在)
* @return {@code true} 如果链表包含指定的元素
* @since 1.6
*/
public boolean removeLastOccurrence(Object o) {
//由于LinkedList中允许存放null,因此下面通过两种情况来分别处理
if (o == null) {
// 遍历链表,从尾结点开始查找指定元素
// 如果查找成功,删除该结点,返回true
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
// 查找失败
return false;
}
/**
* Returns a list-iterator of the elements in this list (in proper
* sequence), starting at the specified position in the list.
* Obeys the general contract of {@code List.listIterator(int)}.<p>
* <p>
* The list-iterator is <i>fail-fast</i>: if the list is structurally
* modified at any time after the Iterator is created, in any way except
* through the list-iterator's own {@code remove} or {@code add}
* methods, the list-iterator will throw a
* {@code ConcurrentModificationException}. Thus, in the face of
* concurrent modification, the iterator fails quickly and cleanly, rather
* than risking arbitrary, non-deterministic behavior at an undetermined
* time in the future.
*
* @param index index of the first element to be returned from the
* list-iterator (by a call to {@code next})
* @return a ListIterator of the elements in this list (in proper
* sequence), starting at the specified position in the list
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see List#listIterator(int)
*/
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
// assert isPositionIndex(index);
next = (index == size) ? null : node(index);
nextIndex = index;
}
public boolean hasNext() {
return nextIndex < size;
}
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
public boolean hasPrevious() {
return nextIndex > 0;
}
public E previous() {
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException();
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex - 1;
}
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
Node<E> lastNext = lastReturned.next;
unlink(lastReturned);
if (next == lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (modCount == expectedModCount && nextIndex < size) {
action.accept(next.item);
lastReturned = next;
next = next.next;
nextIndex++;
}
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* 节点的数据结构,包含前后节点的引用和当前节点
*
* @param <E>
*/
private static class Node<E> {
// 存储的元素
E item;
// 后继结点
Node<E> next;
// 前驱结点
Node<E> prev;
// 前驱结点、存储的元素和后继结点作为参数的构造方法
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
/**
* 返回迭代器
*
* @since 1.6
*/
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
/**
* 因为采用链表实现,所以迭代器很简单
*/
private class DescendingIterator implements Iterator<E> {
private final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}