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类来调用这个方法。
终于真相大白了哈哈哈哈哈。是的,真相永远只有一个!
ArrayList removeRange方法分析的更多相关文章
- ArrayList源码分析--jdk1.8
ArrayList概述 1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合. 2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复. 3. ...
- ArrayList源码分析超详细
ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要分析的类(ztrl+N查找ArraLi ...
- 【Java入门提高篇】Day21 Java容器类详解(四)ArrayList源码分析
今天要介绍的是List接口中最常用的实现类——ArrayList,本篇的源码分析基于JDK8,如果有不一致的地方,可先切换到JDK8后再进行操作. 本篇的内容主要包括这几块: 1.源码结构介绍 2.源 ...
- Java - ArrayList源码分析
java提高篇(二一)-----ArrayList 一.ArrayList概述 ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的.实现了所有可选列表操作,并允许包括 nul ...
- java集合框架03——ArrayList和源码分析
最近忙着替公司招人好久没写了,荒废了不好意思. 上一章学习了Collection的架构,并阅读了部分源码,这一章开始,我们将对Collection的具体实现进行详细学习.首先学习List.而Array ...
- ArrayList源码分析超详细(转载)
ArrayList源码分析超详细 ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要 ...
- ArrayList源码分析(JDK1.8)
概述 ArrayList底层是基于数组实现的,并且支持动态扩容的动态数组(变长的集合类).ArrayList允许空值和重复的元素,当向ArrayList中添加元素数量大于其底层数组容量时,会通过扩容机 ...
- Java ArrayList源码分析(含扩容机制等重点问题分析)
写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...
- 编写测试类,了解ArrayList的方法
这篇文章主要介绍了C#中动态数组用法,实例分析了C#中ArrayList实现动态数组的技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了C#中动态数组用法.分享给大家供大家参考.具体分析如下 ...
- java ArrayList的序列化分析
一.绪论 所谓的JAVA序列化与反序列化,序列化就是将JAVA 对象以一种的形式保持,比如存放到硬盘,或是用于传输.反序列化是序列化的一个逆过程. JAVA规定被序列化的对象必须实现java.io.S ...
随机推荐
- SQL 求中位值
题目A median is defined as a number separating the higher half of a data set from the lower half. Quer ...
- JS插入排序完全理解
插入排序是JS中的一种常见数组排序算法,记录一下如何理解并实现插入排序的功能; 首先看一下最直观的动态图 图片来源:https://www.javascriptc.com/ 从图像可以很直观的看出,插 ...
- pinia - 为 antdv 表格添加加载状态
前言 我们之前制作的 Vue3 + AntDesign Vue + SpringBoot 的增删改查小 Demo 的功能已经全部实现了,但是还是有一点不完美,在发送请求到后端返回数据这一段时间内前台未 ...
- USB总线-Linux内核USB设备驱动ftrace分析(十一)
1.简介 USB Gadget Driver定义了很多trace event,使用者可以在用户空间通过ftrace接口,追踪USB Gadget Driver的行为. USB设备控制器驱动定义的tra ...
- Android Systrace 基础知识 -- Why 60 fps ?
1.正文 今天来讲一下为何我们讲到流畅度,要首先说 60 帧. 我们先来理一下基本的概念: 60 fps 的意思是说,画面每秒更新 60 次 这 60 次更新,是要均匀更新的,不是说一会快,一会慢,那 ...
- Guava中的Joiner和Splitter
目录 Guava 介绍 Joiner list转string map转string 处理嵌套集合 处理null值 Splitter string转list string转map 多个拆分符 输出 代码 ...
- 2024年4月中国数据库排行榜:OceanBase再度登顶,KingBase稳步上升进前五
春风劲吹,迎来了2024年4月中国流行度排行榜.纵观本月榜单,各家数据库产品你追我赶,名次呈现微妙变动,它们正以不可忽视的力量,推动着中国乃至全球的数据管理革新.在这春意盎然的四月,让我们继续关注这些 ...
- 3. 用过Konva吗,用过他的api吗
基础:使用konva,首先需要创建舞台也就是stage,然后创建一个Layer图层,将图层放到舞台上,将图形等内容放到图层上 ; 第一步:创建一个Stage舞台 , 就是创建一个 stage 实例 ...
- .NET云原生应用实践(二):Sticker微服务RESTful API的实现
本章目标 完成数据访问层的基本设计 实现Sticker微服务的RESTful API 引言:应该使用ORM框架吗? 毋庸置疑,Sticker微服务需要访问数据库来管理"贴纸"(也就 ...
- KubeSphere 接入外部 Elasticsearch 最佳实践
作者:张坚,科大讯飞开发工程师,云原生爱好者. 大家好,我是张坚.今天来聊聊如何在 KubeSphere 中集成外置的 ES 组件. KubeSphere 在安装完成时候可以启用日志组件,这样会安装 ...