Java中List集合中subList的坑

参考博主http://blog.csdn.net/xuweilinjijis/article/details/9037635

先看List接口subList方法的javadoc

 The returned list is backed by this list, so non-structural* changes in the returned list are reflected in this list, and vice-versa.* The returned list supports all of the optional list operations supported* by this list.可以看到此方法其实就是直接指向原List集合中的元素,只是改变了开始位置和结束为止而已.如果修改返回对象的数据,那么原对象对应的值也会被修改。看一下List接口具体实现类 ArrayList类,其中的subList方法源码如下
public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);//检查是否越界
        return new SubList(this, 0, fromIndex, toIndex);//返回截取之后的对象
    }

 再接着看一下 SubList类的构造器,JDK源码如下,其实 SubList就是ArrayList中的一个内部类(非静态的),

 private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;//引用调用的父集合
        private final int parentOffset;//父集合的起始位置
        private final int offset;//原对象的起始位置
        int size;//现在集合的大小

        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;
        }
}

  下面是一段造成内存溢出的代码

 List<List<Integer>> cache = new ArrayList<List<Integer>>();
        try {

            while (true) {
                ArrayList<Integer> list = new ArrayList<>();
                for(int j=0;j<100000;j++) {
                    list.add(j);
                }
                List<Integer> subList = list.subList(0, 1);
                cache.add(subList);
            }

        } catch (Exception e) {

        }finally {
            System.out.println("Cache Size=" + cache.size());
        }

  运行结果

Exception in thread "main" Cache Size=815
      java.lang.OutOfMemoryError: GC overhead limit exceeded
     at java.lang.Integer.valueOf(Integer.java:832)
    at com.effectJava.Chapter2.InstrumentedHashSet.main(InstrumentedHashSet.java:44)

看到只包含815个元素就内存溢出啦。就是因为子对象一只引用着父对象,导致父对象无法回收。从而内存溢出



原文地址:https://www.cnblogs.com/09120912zhang/p/8301585.html

时间: 2024-10-11 21:27:24

Java中List集合中subList的坑的相关文章

Java 去除 ArrayList 集合中的重复元素

// One practice package Collection; import java.util.ArrayList; import java.util.Iterator; // 去除 ArrayList 集合中的重复元素 public class ArrayListTest { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) {

java范型集合中的成员排序

范型集合中的类是JsonObject,不是自定义类,如果是自定义类就直接取要比较的字段值. 1 ArrayList<JSONObject> TList = new ArrayList<JSONObject>(); 2 3 for(int i=0;i<10000;i++) 4 { 5 JSONObject object=new JSONObject(); 6 Random rand = new Random(); 7 int randNum = rand.nextInt(200

java之判断集合中的元素是否重复

第1章 判断集合元素唯一的原理 1.1 ArrayList的contains方法判断元素是否重复原理 ArrayList的contains方法会使用调用方法时,传入的元素调用equals方法依次与集合中的旧元素所比较,从而根据返回的布尔值判断是否有重复元素.此时,当ArrayList存放自定义类型时,由于自定义类型在未重写equals方法前,判断是否重复的依据是地址值,所以如果想根据内容判断是否为重复元素,需要重写元素的equals方法. 1.2 HashSet的add/contains等方法判

Java 中List集合中自定义排序

/* 集合框架的工具类. Collections:集合框架的工具类.里面定义的都是静态方法. Collections和Collection有什么区别? Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法. 它有两个常用的子接口, List:对元素都有定义索引.有序的.可以重复元素. Set:不可以重复元素.无序. Collections是集合框架中的一个工具类.该类中的方法都是静态的 提供的方法中有可以对list集合进行排序,二分查找等方法. 通常常用的集合都是线程不

MongoDB中关于查询条件中包括集合中字段的查询

要查询的数据结构例如以下: 以查询当中的versionLimitList字段为例 MongoOperations工具类查询相关语句 <pre name="code" class="java">Criteria criteria1 = Criteria.where("validStartTime").gt(new Date()). and("versionLimitList").elemMatch (Criteria

MongoDB中关于查询条件中包含集合中字段的查询

要查询的数据结构如下: 以查询其中的versionLimitList字段为例 MongoOperations工具类查询相关语句 <pre name="code" class="java">Criteria criteria1 = Criteria.where("validStartTime").gt(new Date()). and("versionLimitList").elemMatch (Criteria.w

Java集合中的Map接口

jdk1.8.0_144 Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap.TreeMap.SortedMap等等,这些最终的子类大多有一个共同的抽象父类AbstractMap.在AbstractMap中实现了大多数Map实现公共的方法.本文介绍Map接口定义了哪些方法,同时JDK8又新增了哪些. Map翻译为“映射”,它如同字典一样,给定一个key值,就能直接定位value值,它的存储结构为

Spring学习笔记--在SpEL中筛选集合

要用到Spring的util(包括util:list等),xml文件中的beans中需要添加一些有关util的信息: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&q

java中的集合操作类(未完待续)

申明: 实习生的肤浅理解,如发现有错误之处,还望大牛们多多指点 废话 其实我写java的后台操作,我每次都会遇到一条语句:List<XXXXX> list = new ArrayList<XXXXX>(); 但是我仅仅只是了解,list这个类是一个可变长用来存储的对象实例的类,我甚至觉得这个List对象可以理解成数组,但是却又与java中咱们正常理解的数组很多的不同,比如说,他的长度可以随着需要自动增长,比如说,实例化一个List类就和咱们声明数组的时候是不一样的! 今天的实习生活