最近在生产上,需要用多线程去处理大量的数据,这个数据在一个list里面,为了避免多个线程拉取同一个list造成多次读写,避免资源同步的问题。决定将数据分割,然后就想到了subList(int from,int to)这个方法。但是发现subList 没有根据for循环的位置进行更新,在此对subList方法进行梳理以及记录。
List接口中有subList(int fromIndex, int toIndex)方法,这个方法返回实现了List接口的SubList的实例,而非当前同类型的实例。Sublist可以简单理解是子List,这个SubList是在AbstractList中定义的,因此只能是包内可见,我们在外面没办法直接访问
它返回原来list的从[fromIndex, toIndex)之间这一部分的视图,之所以说是视图,是因为实际上,返回的list是靠原来的list支持的。所以,你对原来的list和返回的list做的“非结构性修改”(non-structural changes),都会影响到彼此对方。所谓的“非结构性修改”,是指不涉及到list的大小改变的修改。相反,结构性修改,指改变了list大小的修改。
那么,如果涉及到结构性修改会怎么样呢?
如果发生结构性修改的是返回的子list,那么原来的list的大小也会发生变化;而如果发生结构性修改的是原来的list(不包括由于返回的子list导致的改变),那么返回的子list语义上将会是undefined。在AbstractList(ArrayList的父类)中,undefined的具体表现形式是抛出一个ConcurrentModificationException。因此,如果你在调用了sublist返回了子list之后,如果修改了原list的大小,那么之前产生的子list将会失效,变得不可使用。
如果你对一个 List 进行过 subList() 的操作之后,
1. 千万不要再对原 List 进行任何改动的操作(例如: 增删改), 查询和遍历倒是可以. 因为如果对原 List 进行了改动, 那么后续只要是涉及到子 List 的操作就一定会出问题. 而至于会出现什么问题呢? 具体来说就是:
(1) 如果是对原 List 进行修改 (即: 调用 set() 方法) 而不是增删, 那么子 List 的元素也可能会被修改 (这种情况下不会抛出并发修改异常).
(2) 如果是对原 List 进行增删, 那么此后只要操作了子 List , 就一定会抛出并发修改异常.
2. 千万不要直接对子 List 进行任何改动的操作(例如: 增删改), 但是查询和间接改动倒是可以. 不要对子 List 进行直接改动, 是因为如果在对子 List 进行直接改动之前, 原 List 已经被改动过, 那么此后在对子 List 进行直接改动的时候就会抛出并发修改异常.
如果想要实现String.split的效果,争取的截取List的subList ,需要按照如下的方法:
List sub=one.subList(...);
List two=new XxxList(sub);
sub.clear();
————————————————
参考链接:https://blog.csdn.net/clevergump/article/details/51105235