此篇讲解为什么要慎用List.subList(),拆分集合应该使用什么方式
一、我们先添加一组个集合,然后使用subList拆分出一个集合
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("list==1");
list.add("list==2");
list.add("list==3");
list.add("list==4");
list.add("list==5");
System.out.println("list:" + list);
List<String> subList = list.subList(2, 4);
System.out.println("subList:" + subList);
}
subList从第二位开始截取,截取到第四位,来看一下subList的值
似乎一切正常!那么我们在subList之后将list的值修改,看结果
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("list==1");
list.add("list==2");
list.add("list==3");
list.add("list==4");
list.add("list==5");
System.out.println("list:" + list);
List<String> subList = list.subList(2, 4);
list.set(2, "list==3==update");
System.out.println("subList:" + subList);
}
我们在subList之后将list中下标为2的数据(第三个)修改为:"list==3==update",常理来说此时subList已经是一个新集合,没有改动数据应该不会发生变化,但是结果中却显示subList的值也发生了变化。
原因:subList()
方法返回的是原列表的一个视图,而不是一个独立的副本。这意味着对原列表的修改会反映到子列表中,因为它们共享同一份数据存储。
所以执行 list.set(2,
"list==3==update
");
这行代码时,实际上是改变了原列表在索引2位置的值,而这个改变同样会影响到基于原列表创建的子列表 subList
。
为了证实这一点,我们再修改sunList的值
List<String> list = new ArrayList<>();
list.add("list==1");
list.add("list==2");
list.add("list==3");
list.add("list==4");
list.add("list==5");
List<String> subList = list.subList(2, 4);
subList.add("list==5==subList");
System.out.println("list:" + list);
System.out.println("subList:" + subList);
可以看出list的值也被修改
看一下ArrayList中的subList方法
可以看出来,ArrayList的subList方法返回了SubList类,SubList这个类最终也实现了List接口
还有如果subList的toIndex超出了原list的大小会抛出IndexOutOfBoundsException异常
最后如果要拆分list尽量使用Stream处理
// skip:过2个元素、limit:取2个元素
List<String> skipList = list.stream().skip(2).limit(10).collect(Collectors.toList());