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_ ...
随机推荐
- python---memcache使用操作
import memcache mc = memcache.Client(['127.0.0.1:8081'],debug=True) mc.set("key","val ...
- springSession框架来实现sso单点登陆
介绍一下springsession这个框架,其实springsession框架默认的是使用redis来实现单点登陆的,但是不支持redis集群,这个框架的特点是无侵入的实现单点登陆,就是说我们之前获取 ...
- 客户端连接linux经常间隔性断开链接【转】
起因 在使用SecureCRT通过telnet或SSH访问linux时,总是出现过段时间操作就会断开连接提示重连的问题.起初以为是网络不稳定造成的,但我测试发现在服务器端一直可以ping通客户端IP, ...
- np.array和np.asarray区别
- Thrift 安装及使用
前言:由于最近在看storm Topology提交过程的源代码,写好的topology jar文件是通过Thrift RPC的形式提交给nimbus的.故了解下Thrift的基本原理. 参考:http ...
- 重定向printf
#include "stdio.h" #ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else# ...
- golang string int int64转换
#string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt(string, 10, 6 ...
- 20155313 2016-2017-2 《Java程序设计》第五周学习总结
20155313 2016-2017-2 <Java程序设计>第五周学习总结 教材内容学习 第八章 异常处理 程序中总有些意想不到的状况所引发的错误,Java中的错误也以对象方式呈现为ja ...
- DPM 目标检测1
1. Origin 原始目标检测: HOG梯度模型+目标匹配 为了提过对目标形变的鲁棒性(多视角->多组件): 目标形态多样性—>多个模型 目标的动态变化多视角—> 子模型 目标形变 ...
- 初识java和C的不同
学习java语言,发现C语言的语法尽管很类似,但是java的代码编写与C语言却大不相同. 一,java的类,首先接触到的是类这个思想,类中可以定义属性,可以用方法来对属性进行相应的操作: 二,jav ...