java list sublist_Java List的SubList使用问题
一、Sublist导致OOM
代码
@Slf4jpublic classSubListDemo {public static voidsubListOOM() {
List> data = new ArrayList<>();for (int i = 0; i < 1000; i++) {
List rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());//构建一个100000个元素的list
data.add(rawList.subList(0, 1));
}
log.info("data.size(): " +data.size());
}
}
OOM
Exception in thread "File Watcher"java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.io.File.listFiles(File.java:1212)
at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:63)
at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:67)
at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:67)
at org.springframework.boot.devtools.filewatch.FolderSnapshot.collectFiles(FolderSnapshot.java:67)
at org.springframework.boot.devtools.filewatch.FolderSnapshot.(FolderSnapshot.java:58)
at org.springframework.boot.devtools.filewatch.FileSystemWatcher$Watcher.getCurrentSnapshots(FileSystemWatcher.java:277)
at org.springframework.boot.devtools.filewatch.FileSystemWatcher$Watcher.scan(FileSystemWatcher.java:251)
at org.springframework.boot.devtools.filewatch.FileSystemWatcher$Watcher.run(FileSystemWatcher.java:236)
at java.lang.Thread.run(Thread.java:748)
Exception in thread"restartedMain"java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.Integer.valueOf(Integer.java:832)
at java.util.stream.IntPipeline$$Lambda$492/1604894031.apply(Unknown Source)
at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250)
at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.example.newdemo.SubListDemo.subListOOM(SubListDemo.java:17)
at com.example.newdemo.NewdemoApplication.main(NewdemoApplication.java:13)
分析
出现 OOM 的原因是,循环中的 1000 个具有 10 万个元素的 List 始终得不到回收,因为它始终被 subList 方法返回的 List 强引用。
public List subList(int fromIndex, inttoIndex) {
subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);
}
parent 字段就是原始的 List。SubList没有copy一份自己的数据,而是完整的保留了原始的list。 SubList 是原始 List 的视图,并不是独立的 List, SubList 强引用了原始的 List,所以大量保存这样的 SubList 会导致 OOM。
解决
不直接使用 subList 方法返回的 SubList,而是重新使用 new ArrayList,在构造方法传入 SubList,来构建一个独立的 ArrayList。sublist直接释放-》原始的list也被释放。
public static voidsubListWithoutOOM() {
List> data = new ArrayList<>();for (int i = 0; i < 1000; i++) {
List rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());//构建一个100000个元素的list
data.add(new ArrayList<>(rawList.subList(0, 1)));
}
log.info("data.size(): " +data.size());
}
另外一个例子
public static voidremoveSubList() {
List rawList = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());
List subList = rawList.subList(0, 3);
subList.remove(0);
rawList.forEach(System.out::print);
}
2345678910
可以看到,移除sublist的元素后,直接影响到了原始list。
二、修改原始列表后SubList循环报错
测试代码
public static voidaddItemToOriginalList() {
List rawList = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());
List subList = rawList.subList(0, 3);
rawList.add(11);try{
subList.forEach(System.out::print);
}catch(Exception ex)
{
ex.printStackTrace();
}
}
java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099)
at java.util.AbstractList.listIterator(AbstractList.java:299)
at java.util.ArrayList$SubList.iterator(ArrayList.java:1095)
at java.lang.Iterable.forEach(Iterable.java:74)
at com.example.newdemo.SubListDemo.addItemToOriginalList(SubListDemo.java:46)
at com.example.newdemo.NewdemoApplication.main(NewdemoApplication.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
分析
modCount 的字段,表示结构性修改的次数--影响list size修改测次数,add肯定影响size,导致modCount加1.但是sublist的modCount没有变,所有抛出了异常。
代码
private voidcheckForComodification() {if (ArrayList.this.modCount != this.modCount)throw newConcurrentModificationException();
}
java list sublist_Java List的SubList使用问题相关推荐
- java sublist_java 中List.subList 总结
今天,维护以前的代码,看到了List.subList这个方法,以前没接触过,对这个就是个小白,今天学习下: java.util.List中有一个subList方法,用来返回一个list的一部分的视图. ...
- java sublist_java中的subList
package test; import java.util.ArrayList; import java.util.List; //对parentList进行结构性修改,访问subList会抛出异常 ...
- java sublist_java中List.subList()方法的使用
sublist返回的东西,官方解释:Returns a view of the portion of this list between the specified fromIndex, inclus ...
- java中list中sublist_Java 中 List.subList() 方法的使用陷阱
前言 本文原先发表在我的 iteye博客: http://clevergump.iteye.com/admin/blogs/2211979, 但由于在 iteye发表的这篇文章的某些渲染曾经出现过一些 ...
- Java中List集合的subList方法
目录 一.说明 二.测试 1.直接输出 2.向subList中添加元素再输出 3. 从subList中删除元素再输出 4.向list中添加元素再输出 5.从list中删除一个元素后再输出 6.向l ...
- java中list中的subList方法
List<Object> list = new Arraylist<>(); List<Object> subList = list.subList(0, 5); ...
- java sublist_Java subList的使用
1. 在看<阿里巴巴java编程手册的时候>有如下强制约束 顺便学了一下subList. java.util.List中有一个subList方法,用来返回一个list的一部分的视图. Li ...
- java sublist_java 中sublist的使用
http://blog.csdn.net/sbfivwsll/article/details/6557611 java List.subList方法中的超级大陷阱 在使用集合中,可能常常需要取集合中的 ...
- Java中的subList方法
Java中的subList方法 今天看到了java中List中有个subList的方法,感觉很熟悉有没有?没错,在Stirng类中,也有个类似的方法:subString. Stirng中的subStr ...
最新文章
- [置顶] 归并排序,逆序数
- Java使用JAX-WS来写webservice时 Unable to create JAXBContext
- 【深入浅出项目管理视频1】-项目文档评审
- 17.Spark第1部分
- MFC的程序,不想显示窗口,任务栏里也不显示
- LeetCode 1110. 删点成林(二叉树递归)
- centos/Linux 解决使用sudo命令时xxx is not in the sudoers file.This incident will be reported
- [转载] 利用python制作简单计算器
- 7.1 封装(Java包(package)的概念+访问权限修饰符(public/private/protected/default))
- natapp软件使用
- BT5R3安装及汉化
- 鸿蒙系统服务器在哪,鸿蒙的服务中心怎么打开?鸿蒙服务中心打开及关闭教程...
- 外贸企业出口退税流程/经验分享
- 如何理解刑法中的“以非法占有为目的”
- L1-061 新胖子公式 (10 分)
- 浅谈简单快捷的服务器——私有云服务器!
- 轻松易懂的CSS学习权威指南来了
- 涂鸦小程序——为自己的人生画上一笔
- [ERP/鼎捷E10]VMI业务在E10中的处理
- java课程设计之球球大作战
热门文章
- 从编程角度来看此次乐言利用bug上分事件
- 关于8位指针强制转16位隐晦问题
- 文字根据图片环绕 + 显示文字两行后省略号
- 【渝粤教育】国家开放大学2018年春季 8612-21T传染病护理学 参考试题
- 记录服务器宕机事件:解决dell服务器system halted的方法
- 计算机术语表达祝福,祝福新人的唯美句子
- 计算机办公文员是干什么的,文员的基本电脑知识是什么? 文员的基本要求有哪些?...
- (others)U-Boot启动代码分析
- 绝地求生服务器维护5.27,绝地求生5月27日维护到几点进游戏 今天吃鸡更新维护公告...
- win10窗口分屏快捷键