添加hashmap和arraylist时的outofmemory错误

时间:2014-12-29 06:24:54

标签: java arraylist hashmap out-of-memory

我们在csv文件中有大量数据。它有250万行,每行有10个字段,我们正在尝试为每一行准备哈希映射,然后将该hashmap添加到arraylist。

我无法做到这一点,因为巨大的数据导致内存Java堆空间错误丢失。

但我的应用程序需要hashmap列表(我不想增加堆空间)。

reader = new CSVReader(new FileReader(dataFile),',');
         Map<String, String> feedMap = null;
         String[] firstLine;
         String[] nextLine;
         String mappingKey = null;
         String mappingValue = null;
         //Read one line at a time
         firstLine = reader.readNext();
         while ((nextLine = reader.readNext()) != null){
             int i = 0;
             feedMap = new HashMap<String, String>();
             for(String token : nextLine){
                 mappingKey = xmlNodeMap.get(firstLine[i]);                     
                 if (mappingKey != null) {
                     mappingValue = token.trim().length() > 0 ? token : Constants.NO_VALUE;
                     feedMap.put(mappingKey, mappingValue);
                }
                i++;
        }                
       listOfMaps.add(feedMap);
 }

3 个答案:

答案 0 :(得分:2)

这可能听起来很滑稽,但问题是你的应用程序需要一个250万行的列表作为HashMaps。

这是一个荒谬,无理和坦率荒谬的要求;我无法想象这样的数据结构会有什么用处。

将应用程序更改为不需要它。

答案 1 :(得分:0)

您可以尝试使用byte []而不是String对象: byte[] key = mappingKey.getBytes("UTF-8")

每个String对象都包含一组UTF-16字符。在大多数情况下,它表示每个符号2个字节。 UTF-8编码对ASCII使用一个字节,对许多欧洲语言使用两个字节。

每个String对象也包含对char数组的引用。这意味着内存堆中有两个对象:String和char数组。每个对象(甚至只是new Object())的成本约为24字节(取决于版本的Java VM和选项)。

因此,您可以轻松减少对象计数因子2(一个字节[]而不是对String + char []),并且UTF-8符号的数组长度通常小于UTF-16字符的长度。

答案 2 :(得分:0)

完全赞同Bohemian回答。

为了帮助你,我建议你不要一次阅读文件并将所有内容保存在内存中,而是阅读一次,维护一个&#34;索引图&#34; (取决于你的需要)。然后,当您必须对您的文件进行研究时,您将不得不再次打开一个流并使用您的&#34;索引映射&#34;优化搜索时间。

上述解决方案将严重依赖文件访问权限,因此请查看java.nio以获得有效访问权限。