首先想到sublist(int, int)方法
注意此方法参数左闭右开。
测试如下
LinkedList ll = new LinkedList<>();
ll.add("a");
ll.add("b");
ll.add("c");
List l2 = ll.subList(1, 2);//[)
l2.add("new");
System.out.println(ll);
System.out.println(l2);
[a, b, new, c]
[b, new]
可见sublist是快照,sulist插入会影响原list
LinkedList ll = new LinkedList<>();
ll.add("a");
ll.add("b");
ll.add("c");
List l2 = ll.subList(1, 2);//[)
ll.add("d");
System.out.println(ll);
System.out.println(l2);
Exception in thread “main” java.util.ConcurrentModificationException
at java.util.SubList.checkForComodification(AbstractList.java:769)
可见如果更改了原来的list,sublist的任何操作都会报错,包括get() size(),listIterator()等所有调用checkForComodification()的地方。
public List subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
声明:
class SubList<E> extends AbstractList<E>{}
public List subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
声明:
private class SubList extends AbstractList<E> implements RandomAccess {}
看来ArryList处处体现出RandomAccess接口的特性——支持随机访问。
public void clear() {
removeRange(0, size());
}
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
public void clear() {
for (Node x = first; x != null; ) {
Node next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}
截短一个List的正确姿势:
list.subList(from, to).clear();
总之:
subList是返回一个镜像而不是新示例 用了 得保证原来的list不能更改。
之前的抛异常是因为更改了原来的list而要使用sublist的时候必然报异常。
clear的这个跟这个问题说的是如何获得一个list的某一段顺便释放其他节点。
这个操作后原来的list会截取出来 类型不变。
而subList实际上返回的是java.util.Sublist或者java.util.ArrayList.Sublist。