Java中ArrayList和SubList的坑面试题
作者:芝士味的椒盐 发布时间:2023-09-21 06:56:21
代码复现
不要,思考一下会打印出什么?
List<String> list1 = new ArrayList<>(Arrays.asList("username", "passwd"));
List<String> list2 = list1.subList(0, 2);
list2.add("email");
System.out.println(list1);
System.out.println(list2);
执行结果:
你是否感觉疑惑?在想为什么在list2添加的在list1也添加是吧?
源码解析
subList接口
List<E> subList(int fromIndex, int toIndex);
我们使用的是ArrayList,所以是选择ArrayList即可
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
fromIndex是从List元素开始索引,toIndex是List元素结束索引,subListRangeCheck方法是检查是否在允许范围之内。
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
//开始索引小于0
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
//结束索引大于容量
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
//开始索引大于结束索引
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
重头戏在new SubList(this, 0, fromIndex, toIndex);这里,看看下面的SubList就会知道,this关键字将当前对象的引用也就是list1传入了SubList,把传入的list1变成parent赋值给SubList内部成员,然后又将这个构造生成的赋值给list2,也就是说list1和list2是引用了同一个对象,指向的是同一list。
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
//问题就出现在这里
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
再来看看list2.add的源码,将元素直接添加在list1和list2共同的list引用对象上,这就是为什么list2添加了,list1也添加了。
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
//将元素直接添加在list1和list2共同的list引用对象上
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}
附:ArrayList的subList简单介绍和使用
subList(int fromIndex, int toIndex);
它返回原来list的从[fromIndex, toIndex)之间这一部分其实就是list的子列表(注意:fromIndex是 [ 说明包括其本身,toIndex是 )说明不包括其本身)。
这个子列表的本质其实还是原列表的一部分;也就是说,修改这个子列表,将导致原列表也发生改变。
举例说明
list中包含1,2,3,4,5,6一共6个元素,list.subList(1,3)返回的是2,3(list以0为开始)
还有一个经常使用的list.subList(1,list.size)
list中包含1,2,3,4,5,6一共6个元素,list.subList(1,list.size)返回的是2,3,4,5,6(list以0为开始)
来源:https://blog.csdn.net/qq_45860349/article/details/122850216


猜你喜欢
- 1、Spring的事务管理主要包括3个接口TransactionDefinition:封装事务的隔离级别,超时时间,是否为只读事务和事务的传
- 前言AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一。首先,我声明下,我不是
- Java线程的概念和其他多数计算机语言不同,Java内置支持多线程编程(multithreaded programming)。多线程程序包含
- 本文通过实例来介绍如何使用commons-fileupload.jar,Apache的commons-fileupload.jar可方便的实
- C#Process OutputDataReceived事件不触发问题描述项目需要用cmd调用其它软件,实时获取软件处理结果,并根据获取到的
- Spring Security OAuth 默认提供OAuth2.0 的四大基本授权方式(authorization_code\implic
- 官方文档 https://developer.android.google.cn/guide/components/activit
- 在网上也没有找到好的解决方案,于是自己研究了下给解决了,分享给大家,希望对大家能有所帮助。一、异常信息这种情况是因为FTP设置的默认目录引发
- 本文实例为大家分享了Java实现分页功能的具体代码,供大家参考,具体内容如下不用根据改变SQL的形式去查询; 直接查询所有的数据,根据页码自
- 一,为什么说是真正的 * ?阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下 "仿微信打开网页的进度条效
- Eureka注册中心/服务发现框架Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中
- 微信的图片下拽返回功能在日常使用中非常方便,同时在很多 App 中都见到了类似的设计,可以说一旦习惯这种操作再也回不去了。这几天逛 GitH
- 下面是20个非常有用的Java程序片段,希望能对你有用。1. 字符串有整型的相互转换String a = String.valueOf(2)
- 方法● maxBy:获取流中最大元素;minBy:获取流中最小元素● joining:合并,将流中的元素,以字符串的形式拼接起来● summ
- 实现控件拖动的基本原理是对鼠标位置的捕获,同时根据鼠标按键的按下、释放确定控件移动的幅度和时机。 简单示例: 在Grid中有一个Button
- Struts2的核心功能是action,对于开发人员来说,使用Struts2主要就是编写action,action类通常都要实现com.op
- 场景描述在项目开发的过程中,需要修改调试的时候偶每次都需要重启项目浪费时间,下面是我整理的两种常用的两种方式方式一修改启动配置方式(主要针对
- 这篇文章主要介绍了通过实例了解spring使用构造器注入的原因,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 本文实例为大家分享了AndroidStudio实现能在图片上涂鸦的具体代码,供大家参考,具体内容如下一、内容:设计一个能在图片上涂鸦的程序二
- 一,问题采取eureka集群、客户端通过Ribbon调用服务,Ribbon端报下列异常java.net.UnknownHostExcepti