sublist返回的东西,官方解释:Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex bulabula。一个View,视图,想到了数据库视图。
做个实验:
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
List<Object> sub = list.subList(0, 2);// 1,2
sub.add(5);
sub.add(6);
System.out.println("sub:" + sub);
System.out.println("list:" + list);
}
sub:[1, 2, 5, 6]
list:[1, 2, 5, 6, 3, 4]
不仅是sublist,原来的list也增加了。
System.out.println(sub.getClass());
class java.util.ArrayList$SubList
有趣,返回的不是ArrayList,而是里面的子类,源码:
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
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;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index); // 查询也是查的父列表
}
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e); //父列表也【插入】了
this.modCount = parent.modCount;
this.size++;
}
}
于是可以这样这样移除我不想要的数据:
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.subList(3, list.size()).clear();
System.out.println("list:" + list);
}
list:[1, 2, 3]
我突然想这样试一下:
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
List<Object> sub = list.subList(0, 2);// 1,2
sub.add(5);
sub.add(6);
sub.clear();
list.add(7);
list.add(8);
System.out.println("sub:" + sub);
System.out.println("list:" + list);
}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(Unknown Source)
at java.util.ArrayList$SubList.listIterator(Unknown Source)
at java.util.AbstractList.listIterator(Unknown Source)
at java.util.ArrayList$SubList.iterator(Unknown Source)
at java.util.AbstractCollection.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at code.MapTest.main(MapTest.java:20)
果然报错了。。。
直接结论:
前面子类的源码get方法有这么一句: checkForComodification();
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
modCount和父List不一样就报错,这个变量表示当前链表【变化】了几次。
有人解释的很好很详细,Mark:
https://www.zhihu.com/question/24086463
http://www.cnblogs.com/dolphin0520/p/3933551.html