避免subList/subString陷阱
避免subList/subString陷阱
java.util.List接口提供了一个实例方法List<E> subList(int fromIndex, int toIndex), 用于截取 原List 的一个以 fromIndex 为起始索引,以 toIndex 为终止索引(不包括)的子列表。- subString 类似于 subList ,对 String 进行截取。
subList/subString陷阱
subString在本文涉及到的方面都类似于subList,不再赘述
关于函数返回值使用的陷阱
subList的实现代码在AbstractList类里,返回AbstractList的一个子类SubList
class SubList<E> extends AbstractList<E>{
private AbstractList<E> l;
private int offset;
private int size;
//SubList类的构造方法
SubList(AbstractList list, int fromIndex, int toIndex){
//...
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
//...
}
//...
根据以上代码,我们知道,SubList将原来的list赋值给了l,只是改变了偏移量offset。也就是说,subList函数返回了原始list对象的引用。
这也就意味着,对原list和返回的list做的“非结构性修改”(指不涉及list大小改变的修改),都会影响到彼此。
//对返回的list排序,观察原list
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<>();
while(sc.hasNextInt())
{
list.add(sc.nextInt());
}
List<Integer> subList = new ArrayList<>();
subList = list.subList(0, list.size());
subList.sort(null);
for(int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + " ");
sc.close();
}
//输入:
1 3 2 5 4
//输出:
1 2 3 4 5
OOM问题
看到这里读者可能会产生疑问,为什么要用原list的引用作为返回值?
原因在于,这种实现可以提高运行时的性能;
如果创建一个新的list,然后添加所需的内容,这种实现方法无论从内存消耗还是从运行效率来看都远不如直接引用原始list、设置offset和size的方法。
然而,这种返回引用的方法可能会引起一个更加麻烦且难发现的错误:out of memory。
在SubList中,保存了原list的强引用,这意味着,在jvm进行垃圾回收时,只要有一个这样的SubList没有被回收,原List就不会被回收,从而占用这内存空间。当我们只需要长时间保留原List中的一小段数据,却用了subList,而除了SubList中的引用之外,没有其他的引用指向原List,这种情况下,就会造成严重的内存空间的浪费。
可想而知,当这样的subList足够多,jvm没办法及时回收,这些subList就会吃掉所有内存。
如何避免陷阱
正确使用subString/subList
subList/subString适合处理局部的List/String时,比如删除局部的List :
list.subList(begin, end).clear();
subList/subString的一个明显优势在于提高了运行的性能,不用进行冗长的复制过程。所以,如果对程序的性能要求高,可以考虑用subString/subList。
避免使用subList/subString
如果有截取整体中较小的一段来做操作而不改变原整体的需要,或有截取一小段长期保存在内存中的需要
以subList为例:
//...
List<Integer> newList = new ArrayList<>();
for(int i = begin; i < end; i++)
{
//原List为list
newList.add(list.get(i));
}
//...
另外,对于String,可以用
new String()来构造一个新的String来复制需要的部分。
update by 2017/3/30 19:33
by 一棵球
避免subList/subString陷阱的更多相关文章
- 需要注意的subList方法!和substring是不一样的!从源码解释他们的不同。
很多时候我们截取字符串用的是substring方法,很自然用着,但是对于列表的截取时很多时候就用得很少,但是其实他们是很不一样的,具体哪里不一样呢? package main; import java ...
- java List.subList方法中的超级大陷阱
ArrayList 中 subList 的基本用法: subList(fromIndex:int,toIndex:int):List<E> 返回从fromIndex到toindex-1 的 ...
- Java提高配(三七)-----Java集合细节(三):subList的缺陷
我们经常使用subString方法来对String对象进行分割处理,同时我们也可以使用subList.subMap.subSet来对List.Map.Set进行分割处理,但是这个分割存在某些瑕疵. 一 ...
- 1. Longest Palindromic Substring ( 最长回文子串 )
要求: Given a string S, find the longest palindromic substring in S. (从字符串 S 中最长回文子字符串.) 何为回文字符串? A pa ...
- subList和asList
subList subList返回仅仅只是一个视图.直接上源码 public List<E> subList(int fromIndex, int toIndex) { subListRa ...
- Java(jdk1.7) 陷阱
String[] strA = new String[4]; for(int i=0; i<4; i++) { strA[i] = String.valueOf(i); } strA[0] = ...
- Javascript 判断变量类型的陷阱 与 正确的处理方式
Javascript 由于各种各样的原因,在判断一个变量的数据类型方面一直存在着一些问题,其中最典型的问题恐怕就是 typeof null 会返回 object 了吧.因此在这里简单的总结一下判断数据 ...
- 集合之subList的缺陷
我们经常使用subString方法来对String对象进行分割处理,同时我们也可以使用subList.subMap.subSet来对List.Map.Set进行分割处理,但是这个分割存在某些瑕疵. 一 ...
- subString引起的index out of range
特别注意!!!低级坑 subString(begin,end) subList()均存在这个问题. 当end>String.size(),则index out of range!!!
随机推荐
- centos7用户,组及文件权限管理
centos7安装过程中如果没有创建用户的话,默认只有ROOT用户,这个用户是具有最高权限的帐户,可以做任何事情,但实际生产环境中我们一般不会使用这个用户,因为权限太大了,很危险. 所以在生产环境中就 ...
- ASP.NET Core 快速入门【第二弹-实战篇】
上篇讲了asp.net core在linux上的环境部署.今天我们将做几个小玩意实战一下.用到的技术和工具有mysql.websocket.AngleSharp(爬虫html解析).nginx多站点部 ...
- php并发加锁示例
在工作项目中,会遇到一些php并发访问去修改一个数据问题,如果这个数据不加锁,就会造成数据的错误.下面我将分析一个财务支付锁的问题.希望对大家有所帮助. 1 没有应用锁机制 1.1 财务支付简化版本代 ...
- 解决QT编程出现 C2001错误
最近做项目时,在debug输出或者是在其他用到字符串常量的时候,总会时不时的出现C2001错误,提示"常量中有换行符", 比如 tr("删除此设备") 或者 q ...
- Linux逻辑卷管理器concept
Linux逻辑卷管理concept-------------------------转载2013/10/09 通过使用Linux的逻辑卷管理器(Logical Volume Manager, LVM) ...
- Java中常见数据结构List之ArrayList
这里主要包含ArrayList和LinkedList, 然后再添加一个:CopyOnWriteArrayList 关于Java中的集合内容, 感觉都已经被写烂了, 我这里主要是做个复习, 再从扒下源代 ...
- 如何用QUnit为JS代码做单元测试
非常好的入门文章: http://www.zhangxinxu.com/wordpress/2013/04/qunit-javascript-unit-test-%E5%8D%95%E5%85%83% ...
- 一篇文章学会Spring4.0
spring概述 spring 是一个开源框架. Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. Spring 是 ...
- 前端开发中一些好用的chrome插件总结
下载了很多chrome插件和应用,有些是常用的,有些偶尔用一次,有些是不止开发中用的,现做一下总结: 红色是个人认为比较好用的,排名不分先后 1.AppJump管理应用的插件 安装了许多应用之后肯定 ...
- CentOS7下搭建hadoop2.7.3完全分布式
这里搭建的是3个节点的完全分布式,即1个nameNode,2个dataNode,分别如下: CentOS-master nameNode 192.168.11.128 CentOS-node1 ...