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());

解决方案 »

  1.   

    我试了一下,你这字符串100W行大约有70M,那么两个list,应该有100多M。你看看你的jvm有多大?
      

  2.   

    这么多数据查询都是个问题。
    你可否在查询的时候,没有封装进list中时候,分页查询,在sql中直接就将字段分开?
      

  3.   

    你整个算法,因为全都是在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记录,不能体现出回收内存的效果!
      

  4.   


                  for(int i=0;i<list.size();i++){
                String line = list.get(i);
                rows.add(p.split(line));
                 line =null;//java中gc处理机制 试试
                System.out.println(i);
           
            }
      

  5.   


    5楼的方法值得去尝试,不过大数据量的情况下,一直占用着io 还是容易出现jvm溢出问题,不过可以在这基础上利用其他方式:
    如,把内容存入到文件下,当第一个文件大小达到限制后,转存第二个, 在处理的时候可以一次性取出所有文件,然后开几个线程每个线程处理一个问件,;
    这样可以避免大数据量的io,而且也提高了效率