巨多字符串,频繁split,内存溢出

全能码农-ss 2012-03-31 11:05:46
008011;100025;1369491001;新绿色田地;2;0;20111027;29991231;70;70;0;;

类似上边的数据,有100多万行.


100多W已成功导入List<String> lines = new ArrayList<String>();

现在要把每一行,按";" 拆分成String[] .我是循环遍历 lines,每一行 用pattern.split() 拆分.

执行到70多W行的时候就内存溢出了. 有木有别的拆分方式,可以避免内存溢出?

我知道加大内存是个方式.但这个方式不能用.

代码:



List<String>list=new ArrayList<String>();
List<String[]>rows = new ArrayList<String[]>();
String s = "008011;100025;1369491001;新绿色田地;2;0;20111027;29991231;70;70;0;;";
for(int i=0;i<1500000;i++){
list.add(s);
}
String regex = ";";
Pattern p = Pattern.compile(regex);

for(int i=0;i<list.size();i++){
String line = list.get(i);
rows.add(p.split(line));
System.out.println(i);
//每次到70多W行,就内存溢出.咋办??
}
System.out.println(rows.size());
...全文
737 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
dryZeng 2012-03-31
  • 打赏
  • 举报
回复
这得根据需求来。
你直接在内存中生成100多M的内容本来就不合理。
而你jvm肯定也不超过150M。
全能码农-ss 2012-03-31
  • 打赏
  • 举报
回复
如果只split,而不储存String[]到list中 的结果,不会溢出.在想想辙
全能码农-ss 2012-03-31
  • 打赏
  • 举报
回复
楼上的思路,带回我试验下.

发现一问题症结所在了,是拆分之后的数组,存储太多会溢出.



List<String[]>rows = new ArrayList<String[]>();
String s = "008011;100025;1369491001;新绿色田地;2;0;20111027;29991231;70;70;0;;";
String regex = ";";
Pattern p = Pattern.compile(regex);
for(int i=0;i<2000000;i++){
rows.add(p.split(s));
System.out.println(i);
}
System.out.println(rows.size());


如上,某一字符传,split 2000000次,然后存储到List<String[]>中,必然溢出


797611
797612
797613
797614
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.String.substring(String.java:1939)
at java.lang.String.subSequence(String.java:1972)
at java.util.regex.Pattern.split(Pattern.java:1002)
at java.util.regex.Pattern.split(Pattern.java:1059)
at test.file.Test.main(Test.java:18)
白板 2012-03-31
  • 打赏
  • 举报
回复
List<String[]>rows = new ArrayList<String[]>();

溢出的应该是这个 变量吧

可不可以

从文件中按行读的同时,split成string[],写入到文件中

最后再处理这个文件
全能码农-ss 2012-03-31
  • 打赏
  • 举报
回复
从文件中按行读的同时,split成string[],不成功. 也是内存溢出.


我这样,起码能保证都读进来.
  • 打赏
  • 举报
回复
只能Thread.sleep一下了。。
全能码农-ss 2012-03-31
  • 打赏
  • 举报
回复
我试试
全能码农-ss 2012-03-31
  • 打赏
  • 举报
回复
按行读取的同时,split也是内存溢出
aotian16 2012-03-31
  • 打赏
  • 举报
回复
100多W数据都放内存中?
这样不好吧
为什么不一行一行迭代读取
beiouwolf 2012-03-31
  • 打赏
  • 举报
回复
那你为什么要把这么多东西全往内存里塞哪....
难道不能一行一行读取,处理完了先插入一个临时文件或者临时数据库里吗...
噢噢噢噢 2012-03-31
  • 打赏
  • 举报
回复
zj304292653 2012-03-31
  • 打赏
  • 举报
回复
可以自己写分割方法,逐词分析,还有就是用StringBuilder,用正则的那个split效率太低了
神经斌 2012-03-31
  • 打赏
  • 举报
回复
不知道你的业务逻辑是什么,说说我的想法
1.从所给代码上看,容器选的不好,list中的字符串get出来处理完之后,如果没有用了的话,应该及时清除,所以保存读取出来的字符串,用队列比较好,take出来之后队列中就没有了。rows只做了add操作,所以要用List的话也要用LinkedList。
2.处理大量数据,不能一口吃个胖子,分批做才是解决之道,比如一次读入1W条,然后处理这1W条,将结果写入文件,在内存中清除无用的数据。然后再读入下一个1W条...
德薄才浅 2012-03-31
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

如果只split,而不储存String[]到list中 的结果,不会溢出.在想想辙
[/Quote]
可能list.Add有问题用ArrayList做插入删除操作性能不好,换成LinkedList试一试!
Sai 2012-03-31
  • 打赏
  • 举报
回复
List<String>list=new ArrayList<String>();
不要一次全部取出来嘛。。。
chichenzhe 2012-03-31
  • 打赏
  • 举报
回复
你的jvm给你分配的内存太小了.

如果你说改这个被不允许的话.
可以尝试改逻辑结构.

从: 读取(全数存储) --> 循环处理(全数存储) --> 产生一个结果(全数存储)
改为: [分段读取] --> 分段处理 --> 产生结果(丢进list) --> 丢弃结果以外的内存 --> goto [分段读取]

希望你能理解这些伪码

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧