arraylist切割_ArrayList.subList方法的

ArrayList的subList方法返回一个原始列表的视图SubList,对两者进行非结构性修改互相影响。子列表的长度计算至toIndex-1,而非包括toIndex。对子列表进行结构性修改会影响原始列表,反之亦然。为避免原始列表改变,可复制子列表后再操作。使用subList可以便捷地删除指定区间元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在平时,需要取出集合中一部分数据时。通常会使用subList

举个例子:

List list=new ArrayList<>();

list.add("d");

list.add("33");

list.add("44");

list.add("55");

list.add("66");

List list2 = list.subList(0, 2);

System.out.println(list.size());//5

System.out.println(list2.size());//2

ArrayList.subList返回的是其内部类 SubList 的实例(原始列表的一个视图)。

对原来的list和返回的list做的“非结构性修改”(non-structural changes),都会影响到对方。

所谓的“非结构性修改”是指不涉及到list的大小改变的修改。相反,结构性修改,指改变了list大小的修改。

如果发生结构性修改的是返回的子list,那么原来的list的大小也会发生变化;

而如果发生结构性修改的是原来的list(不包括由于返回的子list导致的改变),那么返回的子list语义上将会是undefined。在AbstractList(ArrayList的父类)中,undefined的具体表现形式是抛出一个ConcurrentModificationException。

这也很好理解,在Java的继承体系中,父类永远不知道自己有没有/有多少子类。

取出来的子集长度只有2.查看源代码。

public List subList(int fromIndex, int toIndex) {

return (this instanceof RandomAccess ?

new RandomAccessSubList<>(this, fromIndex, toIndex) :

new SubList<>(this, fromIndex, toIndex));

}

注意这里传的this非常重要,直接将原始list传进去了

.........

跟到最后都是SubList

class SubList extends AbstractList {

private final AbstractList l;

private final int offset;

private int size;

SubList(AbstractList list, int fromIndex, int toIndex) {

if (fromIndex < 0)

throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);

if (toIndex > list.size())

throw new IndexOutOfBoundsException("toIndex = " + toIndex);

if (fromIndex > toIndex)

throw new IllegalArgumentException("fromIndex(" + fromIndex +

") > toIndex(" + toIndex + ")");

l = list;

offset = fromIndex;

size = toIndex - fromIndex;

this.modCount = l.modCount;

}

public E set(int index, E element) {

rangeCheck(index);

checkForComodification();

return l.set(index+offset, element);

}

public E get(int index) {

rangeCheck(index);

checkForComodification();

return l.get(index+offset);

}

public int size() {

checkForComodification();

return size;

}

public void add(int index, E element) {

rangeCheckForAdd(index);

checkForComodification();

l.add(index+offset, element);

this.modCount = l.modCount;

size++;

}

将原始list赋给SubList中的AbstractList l;然而截取的子集长度是size = toIndex - fromIndex;

其实就是到toIndex-1索引的值,举例:list.subList(0, 2)。不是0、1、2三个,子集只是索引0和1的值

大家注意在进行子集add等方法的时候都进行了AbstractList l的操作。所以出现了下面的情况,子集添加时原始list也进行了增加

List list=new ArrayList<>();

list.add("d");

list.add("33");

list.add("44");

list.add("55");

list.add("66");

List list2 = list.subList(0, 2);

list2.add("77");

System.out.println(list.size());//6

System.out.println(list2.size());//3

强调:使用sublist()返回的只是原list对象的一个视图,因此Sublist内部类和ArrayList的内部保存数据的地址是一样得;即它们在内存中是同一个List(集合),只是parentOffset ,size等参数不同

1.如果达到的效果要对子集进行操作,原始list不改变。建议以下方式:

ListtempList =newArrayList(list.subList(2,lists.size()));

tempList.add("xxxxx");

2.我们可以方便的使用如下代码来删除某个区间的序列。

list.subList(from, to).clear();

--------------------- 本文来自 ypp91zr 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/ypp91zr/article/details/52117814?utm_source=copy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值