java之深入理解List.subList()方法

removeRange(int, int);这个方法AbstractList并没有暴露出来,我们应该如何得到一个截短的list?

1 如何得到一个list某个范围的子集sublist

首先想到sublist(int, int)方法 
注意此方法参数左闭右开。 
测试如下

1.1 修改sublist会影响原来的list


 
 
  1. LinkedList<String> ll = new LinkedList<>();
  2. ll. add( "a");
  3. ll. add( "b");
  4. ll. add( "c");
  5. List<String> l2 = ll.subList( 1, 2);
  6. l2. add( "new");
  7. System. out.println(ll);
  8. System. out.println(l2);

[a, b, new, c] 
[b, new] 
可见sublist是快照,sulist插入会影响原list

1.2 修改原list,则sublist的所有操作会报错


 
 
  1. LinkedList<String> ll = new LinkedList<>();
  2. ll. add( "a");
  3. ll. add( "b");
  4. ll. add( "c");
  5. List<String> l2 = ll.subList( 1, 2); //[)
  6. ll. add( "d");
  7. System. out.println(ll);
  8. System. out.println(l2);

Exception in thread “main” java.util.ConcurrentModificationException 
at java.util.SubList.checkForComodification(AbstractList.java:769) 
可见如果更改了原来的list,sublist的任何操作都会报错,包括get() size(),listIterator()等所有调用checkForComodification()的地方。

2 如何正确的截断一个List?

subList()返回的是List!是Sublist,而不是原来的类型。

2.1在java.util.AbstractList.subList(int fromIndex, int toIndex)的定义,返回的是java.util.SubList.SubLis:


 
 
  1. public List<E> subList(int fromIndex, int toIndex) {
  2. return ( this instanceof RandomAccess ?
  3. new RandomAccessSubList<>( this, fromIndex, toIndex) :
  4. new SubList<>( this, fromIndex, toIndex));
  5. }
  6. 声明:
  7. class SubList<E> extends AbstractList<E>{}

2.2 LinkedList并没有覆盖这个方法.ArryList自己覆盖了这个方法,返回的是java.util.ArrayList.SubList:


 
 
  1. public List<E> subList(int fromIndex, int toIndex) {
  2. subListRangeCheck(fromIndex, toIndex, size);
  3. return new SubList( this, 0, fromIndex, toIndex);
  4. }
  5. 声明:
  6. private class SubList extends AbstractList<E> implements RandomAccess {}

看来ArryList处处体现出RandomAccess接口的特性——支持随机访问。

2.3 我们看一下java.util.AbstractList.clear()方法,这正是我们需要的,Sublist的clear就是这个方法


 
 
  1. public void clear() {
  2. removeRange( 0, size());
  3. }

2.3.1 ArrayList的覆盖


 
 
  1. public void clear() {
  2. modCount++;
  3. // clear to let GC do its work
  4. for ( int i = 0; i < size; i++)
  5. elementData[i] = null;
  6. size = 0;
  7. }

 

2.3.2 LinkedList的覆盖


 
 
  1. public void clear() {
  2. for (Node<E> x = first; x != null; ) {
  3. Node<E> next = x. next;
  4. x.item = null;
  5. x. next = null;
  6. x.prev = null;
  7. x = next;
  8. }
  9. first = last = null;
  10. size = 0;
  11. modCount++;
  12. }

3 根据1和2

截短一个List的正确姿势:

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

 

总之: 
subList是返回一个镜像而不是新示例 用了 得保证原来的list不能更改。 
之前的抛异常是因为更改了原来的list而要使用sublist的时候必然报异常。 
clear的这个跟这个问题说的是如何获得一个list的某一段顺便释放其他节点。 
这个操作后原来的list会截取出来 类型不变。 
而subList实际上返回的是java.util.Sublist或者java.util.ArrayList.Sublist。

 

转自:https://blog.csdn.net/kkgbn/article/details/71169680

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值