java list sublist方法_聊聊ArrayList中的subList方法

开发过程中遇到的坑

开发过程经常会使用subList做分页处理。

比如下面的代码

while(pageIndex < maxSize) {

List temp = userIds.subList(pageIndex, (pageIndex + pageSize) > maxSize ? maxSize : (pageIndex + pageSize));

processWechatReserve(temp, unBingdingUserIdList, trueLiveId);

}

private void processWechatReserve(List tempUserIdList, List unBingdingUserIdList, Long targetId){

if (CollectionUtils.isNotEmpty(tempUserIdList) && CollectionUtils.isNotEmpty(unBingdingUserIdList)) {

tempUserIdList.removeAll(unBingdingUserIdList);

当变量unBingdingUserIdList有内容时,

这段代码就会报错IndexOutOfBoundsException。

其实写代码时大家都知道subList是原List的一个视图,

对subList的操作会体现到原List上。

但万万没想到的是调用的方法签名是这样的

processWechatReserve(List, List){

也就是说,实现processWechatReserve方法的人可能并不知道List的来源是subList,此时就很容易出错。

就着本次的问题,萌新也总结了一下使用subList的一些注意事项。

一些例子

1. 元素范围

List subList(int fromIndex, int toIndex)

该方法所取的元素下标为fromIndex至toIndex-1

public List subList(int fromIndex, int toIndex) {

subListRangeCheck(fromIndex, toIndex, size);

return new SubList(this, 0, fromIndex, toIndex);

}

SubList(AbstractList 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;

}

parentOffset就是指向原list

2. 修改

父子list做的非结构性修改(non-structural changes)都会影响到彼此:所谓的“非结构性修改”,是指不涉及到list的大小改变的修改。相反,结构性修改,指改变了list大小的修改。

List list = Lists.newArrayList(1, 3, 5);

List subList = list.subList(0, 1);

subList.set(0, -1);

System.out.println(list);

System.out.println(subList);

[-1, 3, 5]

[-1]

对于结构性修改,子list的所有操作都会反映到父list上。但父list的修改将会导致返回的子list失效。

List list = Lists.newArrayList(1, 3, 5);

List subList = list.subList(0, 1);

subList.remove(0);

System.out.println(list);

System.out.println(subList);

[3, 5]

[]

List list = Lists.newArrayList(1, 3, 5);

List subList = list.subList(0, 1);

list.remove(0);

System.out.println(list);

System.out.println(subList);

[3, 5]

对subList对访问会报异常ConcurrentModificationException

原因:

原list的modCount为4,而subList的modCount为3。

3. 如何删除list中的某段数据:

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

如何避免

如果需要对subList作出修改,又不想动原list。那么可以创建subList的一个拷贝

subList = Lists.newArrayList(subList);

list.stream().skip(strart).limit(end).collect(Collectors.toList());

此刻,我竟然想到了《阿里巴巴Java开发手册》上面有两个提醒与此相关。

纸上得来终觉浅,绝知此事要躬行。

哭出声。。。

2. 【强制】ArrayList的subList结果不可强转成ArrayList,

否则会抛出ClassCastException 异常,

即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。

说明:subList 返回的是 ArrayList 的内部类 SubList,

并不是 ArrayList 而是 ArrayList 的一个视图,

对于 SubList 子列表的所有操作最终会反映到原列表上。

3. 【强制】在 subList 场景中,高度注意对原集合元素的增加或删除,

均会导致子列表的遍历、 增加、删除产生ConcurrentModificationException 异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值