PRELOADER

当前文章 : 《ArrayList源码解读》

10/8/2019 —— 

看前准备

吃大餐前,先来一道开胃菜

完整大餐

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
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable//实现RandomAccess是为了支持快速访问
{
private static final long serialVersionUID = 8683452581122892189L;//版本号,序/反列化用
//默认的初始容量为10
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};//空对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//默认空对象数组
transient Object[] elementData; //存元素数组,transient修饰,不被序列化
// ArrayList中实际数据的数量
private int size;
//----------------------构造函数1-------------------------------
public ArrayList(int initialCapacity) //带初始容量大小的构造函数
{
if (initialCapacity > 0) //初始容量大于0,实例化数组
{
this.elementData = new Object[initialCapacity];
}
else if (initialCapacity == 0) //初始化等于0,将空数组赋给elementData
{
this.elementData = EMPTY_ELEMENTDATA;
}
else //初始容量小于0,抛异常
{
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
//----------------------构造函数2-------------------------------
public ArrayList() //无参构造函数,默认容量为10
{
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//----------------------构造函数3-------------------------------
public ArrayList(Collection<? extends E> c) //创建一个包含collection的ArrayList
{/**☆问题:为什么toArray过了,还要Arrays.copyOf*/
elementData = c.toArray(); //返回包含c所有元素的数组
if ((size = elementData.length) != 0)//将c的元素数赋值给size,如果c的元素个数不为空
{
if (elementData.getClass() != Object[].class)//判断是否为数组类型
elementData = Arrays.copyOf(elementData, size, Object[].class);//复制指定数组,使elementData具有指定长度,Arrays.copyOf浅克隆
}
else
{
//c中没有元素
this.elementData = EMPTY_ELEMENTDATA;
}
}
-------------------------------------------------------------------------------------------
//将当前容量值设为当前实际元素大小
public void trimToSize()
{
modCount++;//记录增删改次数
if (size < elementData.length)
{
elementData = (size == 0)? EMPTY_ELEMENTDATA:Arrays.copyOf(elementData, size);
}
}
------------------------------------扩容原理---------------------------------
/*
如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数.
DEFAULT_CAPACITY 默认的最小值10
EMPTY_ELEMENTDATA 默认为空
*/
//这个方法的主要作用是确定当前集合的容量是否足够,minCapacity参数是所需的最小容量,如果小于则扩容
public void ensureCapacity(int minCapacity) {
//三目运算,如果elementData为空,则minExpand=DEFAULT_CAPACITY=10,否则取0
int minExpand = (elementData != EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY;
//如果小于则扩容
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
//如果大于,说明容量足够
}
-------------------------------------------------------------------------------------------
//这个是1.7之后新加入的,主要是为了内部确保集合容量,与ensureCapacity相似,但是一个是public可以供外部使用,一个是private供内部使用
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
-------------------------------------------------------------------------------------------
private void ensureExplicitCapacity(int minCapacity) {
modCount++;

/**☆问题*/
// 如果当前的实际容量小于需要的最小容量,则扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 这里定义了一个最大的数组长度,为什么会减8个字节了,我查了一下,
// as the Array it self needs 8 bytes to stores the size 2,147,483,648
//暂且理解的意思是需要8个字节来存储数组的长度值,其实这个主要也是由虚拟机决定。
-------------------------------------------------------------------------------------------
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/*
这个是扩容的实现;这里要注意一下,每次的扩容其实是到之前的1.5倍;
oldCapacity + (oldCapacity >> 1) 实际上就是右移除2 结果是3/2oldCapacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //将扩充前的elementData大小给oldCapacity
int newCapacity = oldCapacity + (oldCapacity >> 1);//newCapacity就是1.5倍的oldCapacity
if (newCapacity - minCapacity < 0)//正常扩容为原来的1.5倍,若要扩的容量比1.5倍还多,则扩成要扩的容量
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//如果newCapacity超过了最大的容量限制,就调用hugeCapacity,也就是将能给的最大值给newCapacity
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//新的容量大小已经确定好了,就copy数组,改变容量大小咯。
elementData = Arrays.copyOf(elementData, newCapacity);
}
-------------------------------------------------------------------------------------------
//用来判断是否超出数组最大范围
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

//返回ArrayList的实际大小
public int size() {
return size;
}

//判断ArrayList是否为空
public boolean isEmpty() {
return size == 0;
}

//判断是否包含某个元素
public boolean contains(Object o) {
return indexOf(o) >= 0;
}

//从头开始查找某个元素,返回元素的索引值,注意,我们从源码中可以看到,是可以查找空值的。。并且没有找到是返回-1
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

//反向从最后开始查找,与上面相反
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

//执行克隆,注意这是一个浅克隆,并没有复制数组去创建一个新的,只是将一个新引用指向同一个对象而已。
public Object clone() {
try {
@SuppressWarnings("unchecked")
ArrayList<E> v = (ArrayList<E>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}

//返回集合中元素以数组形式
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}

//以指定T类型数组形式返回
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
//如果数组a的大小<集合的大小,也就是元素的个数
if (a.length < size)
// 返回一个新的T类型的数组,将集合中的元素全部拷贝过去
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//否则数组a的大小>=集合的大小,则直接将集合中的数组全部拷贝到数组a中去
System.arraycopy(elementData, 0, a, 0, size);
//注意:因为数组此时大小是大于集合中的元素的,拷贝之后会有剩余的空间,全部设置为null
if (a.length > size)
a[size] = null;
return a;
}

//返回指定下标的元素
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}

//返回指定下标的元素
public E get(int index) {
rangeCheck(index);//这个方法主要是检查下标是否越界

return elementData(index);
}

//设置指定下标的值
public E set(int index, E element) {
rangeCheck(index);//这个方法主要是检查下标是否越界
//先找到指定位置值
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}

//从尾部添加元素
public boolean add(E e) {
//先扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}

//在指定的下标添加元素
public void add(int index, E element) {
rangeCheckForAdd(index);//是否越界
//扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//第一个elementData代表源数组,index代表从此下标开始截取,第二个elementData代表现在的目标数组,会将前面截取的数组从下标index + 1处开始覆盖
//例如数组{1,2,3,4,5} index=1 ,截取长度size - index为4,则第一个截取为{2,3,4,5},然后从index=2开始覆盖,得到{1,2,2,3,4,5,6}此时数组已经扩容了
//最后设置index=1处值即可,完成添加
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}

//删除指定位置的元素并返回元素的值
public E remove(int index) {
rangeCheck(index);//看下标是否越界

modCount++;

E oldValue = elementData(index);//保存删除的元素

int numMoved = size - index - 1;//代表在index下标之后的全部元素的数量
if (numMoved > 0)//如果index不是最后一个元素
//采用复制数组的方式将index覆盖删除
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; //注意最后还要将最后一个元素设置为空,这是一个多余的重复元素

return oldValue;
}

//删除指定位置的元素,返回是否成功
public boolean remove(Object o) {
//这个比较清晰,注意内部将空的元素与非空元素分开处理的,不过都是从头到尾扫描
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);//如果确认存在这个元素,调用的快速删除
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}

//已经确认了存在要删除的元素,就直接找到删除,与remove()方法内部一样
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}

//清空集合内部所有的元素,遍历设置为空
public void clear() {
modCount++;

// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;

size = 0;
}

//将Collection容器中的元素全部以迭代的方式添加到此列表的尾部
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();//复制数组
int numNew = a.length;//长度
ensureCapacityInternal(size + numNew); // 扩容,准备添加到列表尾部
//取数组a,从0下标开始,长度为numNew,来覆盖数组elementData,下标从size开始,即从最后开始尾部添加
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;//添加完后要相应长度增加
return numNew != 0;//如果参数中的容器元素为空,返回false,否则返回true
}

//从指定位置index处开始添加元素
public boolean addAll(int index, Collection<? extends E> c) {
//与rangeCheck方法功能相似,也是判断下标是否越界,些许的区别是允许边界判断允许等于长度即从尾部开始添加,当然必须大于0啦
rangeCheckForAdd(index);

Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // 这三句与上面一样

/*我还是习惯用实例来分析,假设现在我们本来的列表为elementData={1,3,5,7,9}
参数index=1,a={2,4,6,8},则numMoved = size - index=size + numNew-index=8 注意这里已经扩容了,不然下面的复制操作会报
ArrayIndexOutOfBoundsException异常;即现在新的elementData={1,3,5,7,9,null,null,null,null}
开始逐步分析:
执行这句System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
(1)elementData中从index(包括index)取numMoved长度的数组,即{3,5,7,9,null,null,null,null}
(2)elementData中从index + numNew = 5处(包括index + numNew)开始执行覆盖,即{1,3,5,7,9,3,5,7,9}后面的null舍弃.
执行System.arraycopy(a, 0, elementData, index, numNew);
(1)a数组中从0开始取numNew长度数组,即{2,4,6,8}
(2)elementData从index=1处(包括index)开始执行覆盖,即{1,2,4,6,8,3,5,7,9}
全部过程执行完毕,实现了从index插入数组。
*/
int numMoved = size - index;//这是为了准备取index之后的元素
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);

System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;//如果参数中的容器元素为空,返回false,否则返回true
}

//删除指定位置范围内的元素,从fromIndex(包括)到toIndex(不包括)
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
//此处分析过程与上面一样
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);

// clear to let GC do its work
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;//从这里可以看出其实集合中的实际容量并不止这些,还有将后面的闲置的空间设置为空,便于GC去回收
}
size = newSize;//删除后要更新长度
}

//根据源码的注释说明,这个方法并不会检查index为负数的情况,但是它会在访问数组之前,直接抛出ArrayIndexOutOfBoundsException异常
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

//主要是给add and addAll两个方法判断下标是否越界使用
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

//主要用于抛出异常时定位详细信息
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}


//删除指定Collection中包含的元素,即只要是Collection中含有的元素,在列表中进行删除操作,会得到一个新的列表
public boolean removeAll(Collection<?> c) {
return batchRemove(c, false);
}

//与上面的方法相反,仅仅保留Collection中含有的元素,相当于两个列表取交集
public boolean retainAll(Collection<?> c) {
return batchRemove(c, true);
}

//这个内部方法只分析false过程,true过程相似
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;//获得列表中的数组
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)//遍历列表,如果参数complement传进来默认为fasle
if (c.contains(elementData[r]) == complement)//变量列表中的所有元素是否存在与c中
elementData[w++] = elementData[r];//如果不存在,则将不存在的元素存放在elementData中前列,也就是从头开始覆盖掉与c中重复的元素只保留不同的元素
//这个其实就是找出两个列表中的不同元素放在原始列表的前段,相当于去除了相同的元素;
//如果参数为true,则是找出两个列表中的相同元素放在原始列表的前段,相当于取出了交集元素;
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
//finally中的功能实际上是通过复制覆盖截取列表前段已经找出来的不同元素
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// 主要是为了将列表后半段相同的元素置NULL,便于GC回收
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;//更新列表中的实际元素个数即长度
modified = true;
}
}
return modified;
}
// java.io.Serializable的写入函数
// 将ArrayList的“容量,所有的元素值”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{

int expectedModCount = modCount;//记录标记
s.defaultWriteObject();
//写入“数组的容量”
s.writeInt(size);

// 写入列表中的每一个元素
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
//这个变量我理解的是防止在写入输出流的同时,又在进行列表的删除或添加操作,保证单线程安全问题;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}

//与上面的对应,读取输出流
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;//默认为空

s.defaultReadObject();

s.readInt(); // 从输入流中读取列表容量

if (size > 0) {
// 确保实际容量
ensureCapacityInternal(size);

Object[] a = elementData;
// 将输入流中的所有元素读取出来并赋值
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}

//迭代器
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}

public ListIterator<E> listIterator() {
return new ListItr(0);
}

public Iterator<E> iterator() {
return new Itr();
}
/*Itr内部类,实现了Iterator接口,主要是实现迭代器的功能,也就是设计模式适配器思想,用于迭代出列表中的全部元素,*/
private class Itr implements Iterator<E> {
int cursor; // 默认的返回迭代的下一个元素索引
int lastRet = -1; // 默认的返回最后一个元素的索引,如果数组为空直接返回-1
int expectedModCount = modCount;
//是否还存在下一个元素,即是否迭代到列表尾部
public boolean hasNext() {
return cursor != size;//迭代到尾部返回true,否则返回false
}

//获取下一个元素值
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();//检查线程安全,迭代同时列表是否改变
int i = cursor;
if (i >= size)//先判断是否超出列表容量
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;//获取列表元素数组
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;//记住指向下一个元素索引,便于下次迭代
return (E) elementData[lastRet = i];//更新lastRet值
}
//从尾部开始删除
public void remove() {
if (lastRet < 0)//其实就是-1,则列表为空
throw new IllegalStateException();
checkForComodification();

try {
ArrayList.this.remove(lastRet);//从最后开始删除
cursor = lastRet;
/**☆问题*/
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/*ListItr内部类,继承了Itr类,实现了迭代器功能,主要是继承了ListIterator接口
系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。
ListIterator 没有当前元素;它的光标位置 始终位于调用 previous() 所返回的元素和调用 next() 所返回的元素之间。
长度为 n 的列表的迭代器有 n+1 个可能的指针位置
*/
private class ListItr extends Itr implements ListIterator<E> {
//带参数的构造函数
ListItr(int index) {
super();
cursor = index;
}
/*如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
换句话说,如果 previous 返回一个元素而不是抛出异常,则返回 true)。
其实就是确定当前迭代出的元素是否有前任元素,当迭代出的是第一个元素时,
*/
public boolean hasPrevious() {
return cursor != 0;
}
//返回下一个元素的索引,如果迭代到列表的尾部,则返回列表的大小
public int nextIndex() {
return cursor;
}
//返回当前迭代元素的
public int previousIndex() {
return cursor - 1;
}

@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}

public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

public void add(E e) {
checkForComodification();

try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}

//返回一个新的列表,范围是fromIndex到toIndex
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
//直接用构造函数构建
return new SubList(this, 0, fromIndex, toIndex);
}
//检查下标的范围是否越界
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
/*
SubList内部类,继承了AbstractList抽象类,AbstractList实现了AbstractCollection,适配器设计模式;
实现了RandomAccess接口支持随机访问;
*/
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;//原始列表
private final int parentOffset;//原始列表的偏移量
private final int offset;//偏移量
int size;
//构造函数初始化
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;//初始化为要截取列表的开始下标
this.offset = offset + fromIndex;//初始化为要截取列表的开始下标,这里假定从原始列表的头开始算,初始偏移量为0
this.size = toIndex - fromIndex;//截取的长度
this.modCount = ArrayList.this.modCount;
}
//设置指定下标的值
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;//注意这里还要加上偏移量,因为可能有时候并不是从第一个元素开始;
return oldValue;//并返回被覆盖的元素
}
//获取指定下标的值,并返回值
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
//获取当前列表长度
public int size() {
checkForComodification();
return this.size;
}
//在指定位置添加元素
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}
//删除指定下标的元素
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = parent.remove(parentOffset + index);
this.modCount = parent.modCount;
this.size--;
return result;
}
//删除指定范围内的元素
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
//调用的是AbstractList中的removeRange方法,采用迭代逐一删除元素
parent.removeRange(parentOffset + fromIndex,
parentOffset + toIndex);
this.modCount = parent.modCount;
this.size -= toIndex - fromIndex;
}
//将c中的元素全部添加到当前列表的尾部
public boolean addAll(Collection<? extends E> c) {
return addAll(this.size, c);
}
//将c中的元素全部添加到当前列表的指定index位置
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;//为null直接返回

checkForComodification();
parent.addAll(parentOffset + index, c);
this.modCount = parent.modCount;
this.size += cSize;
return true;
}

public Iterator<E> iterator() {
return listIterator();
}

public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset;

return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount;

public boolean hasNext() {
return cursor != SubList.this.size;
}

@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}

public boolean hasPrevious() {
return cursor != 0;
}

@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
}

public int nextIndex() {
return cursor;
}

public int previousIndex() {
return cursor - 1;
}

public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
ArrayList.this.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

public void add(E e) {
checkForComodification();

try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}
};
}
//返回原始列表范围的部分列表,从fromIndex(包括)开始,到toIndex(不包括)
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, offset, fromIndex, toIndex);
}

private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+this.size;
}

private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
}
}