Java中List集合中subList的坑
参考博主blog.csdn/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;
}
}
  下⾯是⼀段造成内存溢出的代码
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 {ruby 字符串转数组
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个元素就内存溢出啦。就是因为⼦对象⼀只引⽤着⽗对象,导致⽗对象⽆法回收。从⽽内存溢出

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。