zoukankan      html  css  js  c++  java
  • ArrayList removeRange方法分析

     《ArrayList原码分析》一文中提到了“为什么removeRange(int fromIndex,int toIndex)是protected的?”

        先给出removeRange(int fromIndex,int toIndex)方法的源码(这段代码是干什么的就不再解释了,源码分析一文中已经说明)

    复制代码
     1 protected void removeRange(int fromIndex, int toIndex) {
     2     modCount++;
     3     int numMoved = size - toIndex;
     4         System.arraycopy(elementData, toIndex, elementData, fromIndex,
     5                          numMoved);
     6 
     7     // Let gc do its work
     8     int newSize = size - (toIndex-fromIndex);
     9     while (size != newSize)
    10         elementData[--size] = null;
    11     }
    复制代码

        可以看明白removeRange方法将制定范围内的元素都“删除”了,为什么这个方法不暴露给用户使用呢?

        上网查了部分资料,靠谱一点的解释如下:http://stackoverflow.com/questions/2289183/why-is-javas-abstractlists-removerange-method-protected

        再结合例子去验证,看一下代码及执行结果:

    复制代码
    1 public static void main(String[] args) {
    2         ArrayList<Integer> ints = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
    3                 3, 4, 5, 6));
    4         // fromIndex low endpoint (inclusive) of the subList
    5         // toIndex high endpoint (exclusive) of the subList
    6         ints.subList(2, 4).clear();
    7         System.out.println(ints);
    8     }
    复制代码

        运行结果为:[0, 1, 4, 5, 6]

        有没有发现这个结果就像是调用了removeRange(2,4)!这是怎么回事?接着看!

        由于ArrayList并没有实现subList(int fromIndex,int toIndex)方法,所以调用的是父类的方法。看到父类AbstractList的subList方法:

    复制代码
    1 public List<E> subList(int fromIndex, int toIndex) {
    2         return (this instanceof RandomAccess ?
    3                 new RandomAccessSubList<E>(this, fromIndex, toIndex) :
    4                 new SubList<E>(this, fromIndex, toIndex));
    5     }
    复制代码

        ArrayList实现了RandomAccess接口(可以看《ArrayList原码分析》),所以返回RandAccessSubList<E>(this,fromIndex,toIndex)。this、fromIndex、toIndex在上例中分别是ints、2、4。

        下面是RandAccessSubList<E>(this,fromIndex,toIndex)的源码。

    复制代码
    1 class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    2     RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
    3         super(list, fromIndex, toIndex);
    4     }
    复制代码

        只是调用了父类的构造方法。下面给出被调用的构造方法。

    复制代码
     1 SubList(AbstractList<E> list, int fromIndex, int toIndex) {
     2         if (fromIndex < 0)
     3             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
     4         if (toIndex > list.size())
     5             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
     6         if (fromIndex > toIndex)
     7             throw new IllegalArgumentException("fromIndex(" + fromIndex +
     8                                                ") > toIndex(" + toIndex + ")");
     9         l = list;
    10         offset = fromIndex;
    11         size = toIndex - fromIndex;
    12         expectedModCount = l.modCount;
    13     }
    复制代码

        至此subList方法调用结束。接着看clear()方法。由于subList方法返回的是List<E>所以该clear方法将调用AbstractList类的clear()方法。

    复制代码
    1     public void clear() {
    2         removeRange(0, size());
    3     }
    复制代码

        终于看到removeRange了,看到希望了。

    复制代码
    1 protected void removeRange(int fromIndex, int toIndex) {
    2         checkForComodification();
    3         l.removeRange(fromIndex+offset, toIndex+offset);
    4         expectedModCount = l.modCount;
    5         size -= (toIndex-fromIndex);
    6         modCount++;
    7     }
    复制代码

        这是被调用的removeRange方法,看到没有,里面执行了l.removeRange(fromIndex+offset,toIndex+offset),知道l是谁吗?l定义在SubList中,还记得嗲用SubList方法传入的list吗?还记得调用subList时传入的this吗?还记得大明湖畔的夏雨荷吗?!!!跑题了~~~

        至此将进入ArrayList的removeRange(int fromIndex,int toIndex)方法。绕了一个大弯终于通过调到了这个方法,可是又有一个疑问了:调用了subList了不是通过返回的List<E>调用了clear吗?仔细观察会发现其实传到SubList构造方法中并被保存的一直是原来的ArrayList,所以调用removeRange的时候毫无疑问是对原先的List进行了处理!!!

        在结合那段英文的解释,为了避免冗余......所以没对用户开放,当然你可以继承ArrayList编写自己的List类来调用这个方法。

        终于真相大白了哈哈哈哈哈。是的,真相永远只有一个!

  • 相关阅读:
    notepad++ 安装
    Git 安装
    C 字符串常量 数据类型
    vue路由传参query和params的区别
    mysql 在 centos 上安装,做成服务,且开机启动 步骤
    全网最详细Apache Kylin1.5安装(单节点)和测试案例 ---> 现在看来 kylin 需要 安装到Hadoop Master 节点上
    Kylin build cube step 2 报错(Kylin 安装在slave 节点上)
    Kylin build cube step 2 报错
    Kylin 环境 搭建 成功
    Kylin 环境 搭建 报错
  • 原文地址:https://www.cnblogs.com/daichangya/p/12959399.html
Copyright © 2011-2022 走看看