javaAPI深入理解(1)如何截短一个List以及List.subList()方法的坑

来源:互联网 发布:mac查看股票行情 编辑:程序博客网 时间:2024/05/07 22:46

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

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

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

1.1 修改sublist会影响原来的list

    LinkedList<String> ll = new LinkedList<>();    ll.add("a");    ll.add("b");    ll.add("c");    List<String> l2 =  ll.subList(1, 2);//[)    l2.add("new");    System.out.println(ll);    System.out.println(l2);

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

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

    LinkedList<String> ll = new LinkedList<>();    ll.add("a");    ll.add("b");    ll.add("c");    List<String> l2 =  ll.subList(1, 2);//[)    ll.add("d");    System.out.println(ll);    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:

 public List<E> subList(int fromIndex, int toIndex) {        return (this instanceof RandomAccess ?                new RandomAccessSubList<>(this, fromIndex, toIndex) :                new SubList<>(this, fromIndex, toIndex));    }    声明:    class SubList<E> extends AbstractList<E>{}

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

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

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

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

    public void clear() {        removeRange(0, size());    }

2.3.1 ArrayList的覆盖

    public void clear() {        modCount++;        // clear to let GC do its work        for (int i = 0; i < size; i++)            elementData[i] = null;        size = 0;    }

2.3.2 LinkedList的覆盖

    public void clear() {        for (Node<E> x = first; x != null; ) {            Node<E> next = x.next;            x.item = null;            x.next = null;            x.prev = null;            x = next;        }        first = last = null;        size = 0;        modCount++;    }

3 根据1和2

截短一个List的正确姿势:

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

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

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牙结石掉了有洞怎么办 内衣的钩子会掉怎么办? 新胸罩肩带老掉怎么办 牙齿少了一小块怎么办 儿童牙齿有黑斑要怎么办 牙齿又黄又臭怎么办 大牙烂空了很臭怎么办 牙齿已经烂没了怎么办 牙齿已经蛀没了怎么办 牙齿整个蛀掉了怎么办 小孩恒牙长歪了怎么办 孩子换牙长歪了怎么办 9岁门牙磕松动了怎么办 牙齿摔断了一半怎么办 牙齿从根部断了怎么办 牙断了还有牙根怎么办 牙根断在牙龈里怎么办 后槽牙掉了一半怎么办 孩子门牙摔断了怎么办 2岁宝宝牙齿断了怎么办 小孩乳牙摔掉了怎么办 9孩子门牙磕断了怎么办 牙齿断了但没掉怎么办 大人门牙摔断了怎么办 兔子内牙太长了怎么办 牙齿整个摔断了怎么办 大门牙摔断了怎么办 23岁门牙磕断了怎么办 门牙齿断了一半怎么办 牙齿从中间裂开了怎么办 牙齿断了牙根还在怎么办 手指被兔子咬了怎么办 被家兔咬出血了怎么办 儿童被兔子咬了怎么办 兔子上牙太长了怎么办 兔子牙长出来了怎么办 有做美容冠后悔怎么办 2岁牙釉质损坏怎么办 牙釉质被磨掉了怎么办 孩子牙釉质掉了怎么办 3岁牙釉质脱落怎么办