java List.subList方法中的超级大陷阱
ArrayList 中 subList 的基本用法:
| subList(fromIndex:int,toIndex:int):List<E> | 返回从fromIndex到toindex-1 的 子列表 |
在使用集合中,可能常常需要取集合中的某一部分子集来进行一下操作,于是subList这个方法就映入我们的眼帘,毫不犹豫地使用。
例如以下代码:
public static void main(final String[] args) {
List<Object> lists = new ArrayList<Object>();
lists.add("1");
lists.add("2");
lists.add("3");
lists.add("4");
List<Object> tempList = lists.subList(2, lists.size());
tempList.add("6");
System.out.println(tempList); // 1
System.out.println(lists); // 2
}
输出:
[3, 4, ]
[1, 2, 3, 4, ]
改变tempList元集合也改变了
代码初步写好后,可能我们想达到的效果是:往集合lists的子集合tempList中添加一个元素6,而原有的集合保持不变。
即到达这样的效果:lists = [1, 2, 3, 4],tempList = [3, 4, 6]。但是我们看到实际的结果确是lists里边也添加了元素6。
这是怎么一会事呢,通过查找java原代码我们可以看到:tempList的subList实现代码在AbstractList类里边,然而无论如何,最终的结果都是返回一个AbstractList的子类:SubList(该类是一个使用默认修饰符修饰的类,其源代码位于AbstractList.java类文件里边),
SubList类的构造方法:
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
expectedModCount = l.modCount;
}
里边,将我们原有的list对象给缓存到SubList类对象的一个属性中去了。
而SubList类的add/remove等修改元素的方法中,都使用l进行了操作:
public void add(int index, E element) {
if (index<0 || index>size)
throw new IndexOutOfBoundsException();
checkForComodification();
l.add(index+offset, element);
expectedModCount = l.modCount;
size++;
modCount++;
}
因此,当我们使用子集合tempList进行元素的修改操作时,会影响原有的list集合。所以在使用subList方法时,一定要想清楚,是否需要对子集合进行修改元素而不影响原有的list集合。
如果需要对子集合的元素进行修改操作而不需要影响原集合时,我们可以使用以下方法进行处理:
public static void main(final String[] args) public static void main(final String[] args) {
List<Object> lists = new ArrayList<Object>();
lists.add("1");
lists.add("2");
lists.add("3");
lists.add("4");
//注意这里是和本文顶部的代码不同的....
List<Object> tempList = new ArrayList<Object>(lists.subList(2, lists.size()));
tempList.add("6");
System.out.println(tempList); // 1
System.out.println(lists); // 2
}
输出:
[3, 4, ]
[1, 2, 3, 4]
改变tempList元集合 不变
java List.subList方法中的超级大陷阱的更多相关文章
- 在主方法中定义一个大小为50的一维整型数组,数组i名为x,数组中存放着{1,3,5,…,99}输出这个数组中的所有元素,每输出十个换一行
package hanqi; import java.util.Scanner; public class Test7 { public static void main(String[] args) ...
- 在主方法中定义一个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。
//在主方法中定义一个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’:输出这个数组中的所有元素. char [][]y=new char [10][10 ...
- 16.按要求编写Java应用程序。 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。
//分类 package com.bao; public class Shuchu { int[]yi=new int[50]; String[][]er=new String[10][10]; vo ...
- 按要求编写Java应用程序。 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。
int[]x=new int [50]; char[][]y=new char[10][10]; int j=1,w=0; for(int i=0;i<50;i++) { x[i]=j; j+= ...
- java 访问器方法中对象引用的问题
"注意不要编写返回引用可变对象的访问器方法".因为会破坏类的封装性,引用的内容可能会被改变,产生业务逻辑上的错误. 什么是可变对象? 先要搞清楚java中值传递和引用传递的问题,总结如下: 1.对象就 ...
- [改善Java代码]注意方法中传递的参数要求(replaceAll和replace的区别)
有这样一个简单的需求:写一个方法,实现从原始字符串中删除与之匹配的所有子字符串,比如"蓝蓝的天,白云飘"中,删除"白云飘",输出"蓝蓝的天," ...
- java 关于getProperty()方法中反斜杠问题
问: 在配置文件a.properties中有一行path=C:\test在java中getProperty("path")后,java把\t认为是一个字符TAB.怎样才能取到正确的 ...
- java的split方法中的regex参数
我们需要以|进行分割,为了匹配|本身,正则中采用\|进行转义,而Java中\也表示转义,从java到正则需要必须使用\\|进行转义,即split中的\\表示正则的转义.
- java实现求数组中元素第二大的元素
/** * 找出数组中数第二大的值 * @param array * @date 2016-9-25 * @author shaobn */ public static void getMethod_ ...
随机推荐
- spring tool suite处理 maven项目名称红色感叹号的问题
今天构建一个springboot项目时,发现项目有个红色感叹号,但是pom.xml跟Build Path 都没问题. 解决方案: 选择 Windows --> show view --> ...
- jquery ajax 跨域请求【原】
前台 function sending(){ $.ajax({ type : "get",//jsonp只能get async:true, url : "/webcont ...
- Storm Topology 提交 总结---Kettle On Storm 实现
一,目的 在学习的过程中,需要用到 PDI---一个开源的ETL软件.主要是用它来设计一些转换流程来处理数据.但是,在PDI中设计好的 transformation 是在本地的执行引擎中执行的,(参考 ...
- Linux 重启网卡失败 Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details.
linux下重启网卡使用命令 : service network restart 时报错: [root@slave01 hadoop]# service network restart Startin ...
- luogu P4778 Counting swaps
计数套路题?但是我连套路都不会,,, 拿到这道题我一脸蒙彼,,,感谢@poorpool 大佬的博客的指点 先将第\(i\)位上的数字\(p_i\)向\(i\)连无向边,然后构成了一个有若干环组成的无向 ...
- POJ1751 Highways【最小生成树】
题意: 给你N个城市的坐标,城市之间存在公路,但是由于其中一些道路损坏了,需要维修,维修的费用与公路长成正比(公路是直的). 但现有M条公路是完整的,不需要维修,下面有M行,表示不需要维修的道路两端的 ...
- Servlet3.0的注解自定义原生Listener监听器实战
简介:监听器介绍和Servlet3.0的注解自定义原生Listener监听器实战 自定义Listener(常用的监听器 servletContextListener.httpSessionListen ...
- 【ANT】ant使用
官网:https://ant.apache.org/,task介绍:https://ant.apache.org/manual/index.html 0.介绍: Ant的构建文件当开始一个新的项目时, ...
- MySQL基于LVM快照的备份恢复(临时)
目录1.数据库全备份2.准备LVM卷3.数据恢复到LVM卷4.基于LVM快照备份数据5.数据灾难恢复6.总结 写在前面:测试环境中已安装有mysql 5.5.36数据库,但数据目录没有存放在LVM卷, ...
- kafka系列三、Kafka三款监控工具比较
转载原文:http://top.jobbole.com/31084/ 通过研究,发现主流的三种kafka监控程序分别为: Kafka Web Conslole Kafka Manager KafkaO ...