巨多字符串,频繁split,
内存溢出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行的时候就内存溢出了. 有木有别的拆分方式,可以避免内存溢出?
我知道加大内存是个方式.但这个方式不能用.
代码:
Java code
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());
------解决方案--------------------我试了一下,你这字符串100W行大约有70M,那么两个list,应该有100多M。
你看看你的jvm有多大?
------解决方案--------------------
你整个算法,因为全都是在List中,所以相当于永远也没法释放内存了,那么原始数据和拆分后的数据,都要完整保存在内存中。所以光靠更改切分方式是不可能降低内存开销的。
如果不能加大内存,就考虑另外两个方案:
1、借助文件做流式处理:把原始list先存在文件中,然后逐行读取,处理后的结果写入另一个文件中;这种做法内存开销最小,基本上就是几个字符串的开销而已。
2、边做边删:也就是在循环处理原始list的时候,把list的元素同时删除掉,做一笔就删除一笔。
强烈建议方式 1 !方式2类似于:
int i = list.size()-1;
for( ;i >= 0; i--){
String line = list.get(i);
rows.add(p.split(line));
System.out.println(i);
list.remove(i); // 关键是这句话,这样原始的那行字符串就可以被释放了。
}
但是!!因为在你的例子里面,所有list的元素都是引用同一个 String s,所以在你的测试函数中,删除原始list记录,不能体现出回收内存的效果!
------解决方案--------------------