背景
刚开始截取List集合时使用笨的方法自己截取,后来发现Java api 有方法使用 subList方法,但是由于不清楚原理拿来就用,做项目就掉坑里了
List<UclassUser> subList = list.subList(0, GameRoom.CAPACITY / 2);
subList.forEach(item -> {
item.setRoomId(newRoom.getId());
newRoom.getStuList().add(item.getUserId());
});
list.removeAll(subList);
studentAlreadyList.addAll(subList);
就是这些代码报的错,大家可以自行去看
查看源码
原来subList方法是new 了一个SubList对象把原来的list引用传了进去,所以返回的SubList对象,SubList对象也只是源集合的影像,不是新的List,所以你要是操作源集合,那么就会报异常
throw new ConcurrentModificationException()
这种类型的异常 fail-fast,在Java中叫快速失败,有兴趣的可以去查资料
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 + ")");
}
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;
}
总结
最后解决办法用新的list去接受一下,就可以操作原来的集合了
List<UclassUser> subList = new ArrayList<>(list.subList(0, GameRoom.CAPACITY / 2));
subList.forEach(item -> {
item.setRoomId(newRoom.getId());
newRoom.getStuList().add(item.getUserId());
});
list.removeAll(subList);
studentAlreadyList.addAll(subList);