ArrayList removeRange方法分析

简介: 《ArrayList原码分析》一文中提到了“为什么removeRange(int fromIndex,int toIndex)是protected的?”     先给出removeRange(int fromIndex,int toIndex)方法的源码(这段代码是干什么的就不再解释了,源...

    《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类来调用这个方法。

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

 

如果本文对您有帮助,点一下右下角的“推荐”
目录
相关文章
|
算法 Dubbo NoSQL
Java中5种List的去重方法及它们的效率对比,你用对了吗?
01、使用两个for循环实现List去重(有序) /**使用两个for循环实现List去重(有序) * * @param list * */ public static List removeDuplicationBy2For(List<Integer> list) { for (int i=0;i<list.size();i++) { for (int j=i+1;j<list.size();j++) { if(list.get(i).equa
24486 2
Java中5种List的去重方法及它们的效率对比,你用对了吗?
|
1月前
|
存储 Java API
从源码角度解析ArrayList.subList的几个坑!
从源码角度解析ArrayList.subList的几个坑!
|
1月前
|
存储 Java 编译器
Collection-ArrayList源码解析
Collection-ArrayList源码解析
15 0
|
3月前
|
存储 Java 数据处理
如何使用 Java 迭代 HashMap 中的 ArrayList
【8月更文挑战第23天】
49 2
|
6月前
|
存储 安全 Java
基于ArrayList源码探讨如何使用ArrayList
基于ArrayList源码探讨如何使用ArrayList
|
11月前
|
C#
C# 集合(ArrayList)的方法和使用
C# 集合(ArrayList)的方法和使用
|
Java
ArrayList 分析以及相关方法介绍
java.util.ArrayList 是我们最常用的一个类,ArrayList 底层是动态数组,读者可以把它理解为数组的实现
104 0
ArrayList 分析以及相关方法介绍
|
存储 C#
简单数据结构类——Arraylist
简单数据结构类——Arraylist
105 0
|
存储
ArrayList的retainAll()方法使用
retainAll()方法:list1.retainAll(list2),即list1调用retainAll()方法得到list1和list2的交集并存储在list1中,这个方法的返回值是boolean型,true代表方法执行成功。 @Test public void test1() { ArrayList arrayList1 = new ArrayList(); arrayList1.add(123); arrayList1.add.
280 0
|
存储 Java 容器
Java中ArrayList,LinkedList,Vector三者的异同点及其使用场景和ArrayList的一些常用方法
相同点:三者存储的都是有序,可重复的数据。 异:①:ArrayList底层存储类型树Object数组,而LinkedList底层是双向链表 ②:ArrayList和Vector调用创建空参构造器创建对象时,默认的size是10,但是当自动扩容的时候,ArrayList扩容为当前容器size的1.5倍,而Vector自动扩容为当前的2倍。 使用场景:①:当查找操作比较多时,使用ArrayList,因为其底层是数组实现,可以根据角标查找,时间复杂度是O(1),而LinkedList底层是双向...
137 0