避免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陷阱的更多相关文章

  1. 需要注意的subList方法!和substring是不一样的!从源码解释他们的不同。

    很多时候我们截取字符串用的是substring方法,很自然用着,但是对于列表的截取时很多时候就用得很少,但是其实他们是很不一样的,具体哪里不一样呢? package main; import java ...

  2. java List.subList方法中的超级大陷阱

    ArrayList 中 subList 的基本用法: subList(fromIndex:int,toIndex:int):List<E> 返回从fromIndex到toindex-1 的 ...

  3. Java提高配(三七)-----Java集合细节(三):subList的缺陷

    我们经常使用subString方法来对String对象进行分割处理,同时我们也可以使用subList.subMap.subSet来对List.Map.Set进行分割处理,但是这个分割存在某些瑕疵. 一 ...

  4. 1. Longest Palindromic Substring ( 最长回文子串 )

    要求: Given a string S, find the longest palindromic substring in S. (从字符串 S 中最长回文子字符串.) 何为回文字符串? A pa ...

  5. subList和asList

    subList subList返回仅仅只是一个视图.直接上源码 public List<E> subList(int fromIndex, int toIndex) { subListRa ...

  6. Java(jdk1.7) 陷阱

    String[] strA = new String[4]; for(int i=0; i<4; i++) { strA[i] = String.valueOf(i); } strA[0] = ...

  7. Javascript 判断变量类型的陷阱 与 正确的处理方式

    Javascript 由于各种各样的原因,在判断一个变量的数据类型方面一直存在着一些问题,其中最典型的问题恐怕就是 typeof null 会返回 object 了吧.因此在这里简单的总结一下判断数据 ...

  8. 集合之subList的缺陷

    我们经常使用subString方法来对String对象进行分割处理,同时我们也可以使用subList.subMap.subSet来对List.Map.Set进行分割处理,但是这个分割存在某些瑕疵. 一 ...

  9. subString引起的index out of range

    特别注意!!!低级坑 subString(begin,end)   subList()均存在这个问题. 当end>String.size(),则index out of range!!!

随机推荐

  1. 解决UIViewController中添加子控制器viewWillAppear不调用问题

    问题描述: 我在UICollectionViewController中添加子控制器数组, 并在cellForItem中把子控制器数组中对应的控制器对应的view添加到了UICollectionView ...

  2. Autofac in webapi2

    安装包:Autofac.webapi2 注意: install-package autofac.webapi2 (注意:您的项目中如果使用的是webapi2,此处必须为webapi2而不是webapi ...

  3. Android Studio设置快捷键和背景

    1.快捷键设置 复制代码并且向下移动 向下移动代码 代码提示 代码改错 更改文件名称   alt + shift + R   2.更改背景颜色-豆绿色           来自为知笔记(Wiz)

  4. SpringMVC实现垂直搜索引擎

    本篇博客是在上一篇<Lucene搜索引擎+HDFS+MR完成垂直搜索>的基础上,在数据收集之后的JSP/Servlet方面,换为SpringMVC框架来实现. 借助SpringMVC技术完 ...

  5. js原型学习

    js中所有对象都存在一个隐式原型_ _proto_ _,指向创建这个对象的函数的原型prototype; 而函数的原型prototype都是Object函数的一个对象,也有隐式原型,指向的就是Obje ...

  6. XP和win7的软件崩溃提示

    运行在XP上的应用软件崩溃时总提示:应用程序错误,xxxxx地址不能写... 现在win7上提示的就只有关闭和调试程序,没有这些详细信息.其实win7下面也记录了相关的信息. 位置在:“控制面板” - ...

  7. 无法远程连接mysql,连接后也没有权限创建数据库

    问题现象:无法远程连接mysql,连接后也没有权限创建数据库 问题原因: MySql-Server 出于安全方面考虑只允许本机(localhost, 127.0.0.1)来连接访问. 这对于 Web- ...

  8. JSP 页面传值方法总结(转)

    原文地址:http://www.cnblogs.com/java-class/p/6358964.html 阅读目录 1. URL 链接后追加参数 2. Form 3. 设置 Cookie 4. 设置 ...

  9. 【Ubuntu 16】安装deb

    deb是debian linux的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb  dpkg 是Debian Package的简写,是为Debian ...

  10. 【Hadoop】集群配置要点

    1.SSH免密码登录 1.1生成公钥,一直enter,直到完成 dream361@master:~$ ssh-keygen -t rsa 1.2传送公钥 dream361@master:~$ scp ...