巨多字符串,频繁split,内存溢出解决思路
巨多字符串,频繁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行的时候就内存溢出了. 有木有别的拆分方式,可以避免内存溢出?
我知道加大内存是个方式.但这个方式不能用.
代码:
------解决方案--------------------
那你为什么要把这么多东西全往内存里塞哪....
难道不能一行一行读取,处理完了先插入一个临时文件或者临时数据库里吗...
------解决方案--------------------
100多W数据都放内存中?
这样不好吧
为什么不一行一行迭代读取
------解决方案--------------------
List<String[]>rows = new ArrayList<String[]>();
溢出的应该是这个 变量吧
可不可以
从文件中按行读的同时,split成string[],写入到文件中
最后再处理这个文件
------解决方案--------------------
你的jvm给你分配的内存太小了.
如果你说改这个被不允许的话.
可以尝试改逻辑结构.
从: 读取(全数存储) --> 循环处理(全数存储) --> 产生一个结果(全数存储)
改为: [分段读取] --> 分段处理 --> 产生结果(丢进list) --> 丢弃结果以外的内存 --> goto [分段读取]
希望你能理解这些伪码
------解决方案--------------------
不知道你的业务逻辑是什么,说说我的想法
1.从所给代码上看,容器选的不好,list中的字符串get出来处理完之后,如果没有用了的话,应该及时清除,所以保存读取出来的字符串,用队列比较好,take出来之后队列中就没有了。rows只做了add操作,所以要用List的话也要用LinkedList。
2.处理大量数据,不能一口吃个胖子,分批做才是解决之道,比如一次读入1W条,然后处理这1W条,将结果写入文件,在内存中清除无用的数据。然后再读入下一个1W条...
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());
------解决方案--------------------
那你为什么要把这么多东西全往内存里塞哪....
难道不能一行一行读取,处理完了先插入一个临时文件或者临时数据库里吗...
------解决方案--------------------
100多W数据都放内存中?
这样不好吧
为什么不一行一行迭代读取
------解决方案--------------------
List<String[]>rows = new ArrayList<String[]>();
溢出的应该是这个 变量吧
可不可以
从文件中按行读的同时,split成string[],写入到文件中
最后再处理这个文件
------解决方案--------------------
你的jvm给你分配的内存太小了.
如果你说改这个被不允许的话.
可以尝试改逻辑结构.
从: 读取(全数存储) --> 循环处理(全数存储) --> 产生一个结果(全数存储)
改为: [分段读取] --> 分段处理 --> 产生结果(丢进list) --> 丢弃结果以外的内存 --> goto [分段读取]
希望你能理解这些伪码
------解决方案--------------------
不知道你的业务逻辑是什么,说说我的想法
1.从所给代码上看,容器选的不好,list中的字符串get出来处理完之后,如果没有用了的话,应该及时清除,所以保存读取出来的字符串,用队列比较好,take出来之后队列中就没有了。rows只做了add操作,所以要用List的话也要用LinkedList。
2.处理大量数据,不能一口吃个胖子,分批做才是解决之道,比如一次读入1W条,然后处理这1W条,将结果写入文件,在内存中清除无用的数据。然后再读入下一个1W条...