【问题标题】:Best way to load a large file into arraylist in java在java中将大文件加载到arraylist的最佳方法
【发布时间】:2012-12-04 11:15:29
【问题描述】:

我有一个大小约为 300mb 的文件。我想逐行读取内容,然后将其添加到 ArrayList 中。所以我创建了一个数组列表 a1 的对象,然后使用 BufferedReader 读取文件,之后当我将文件中的行添加到 ArrayList 中时,它在线程“main” java.lang.OutOfMemoryError: Java heap space 中给出错误异常。

请告诉我应该如何解决这个问题。

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
      FileReader file = new FileReader(
          "/home/dmdd/Desktop/AsiaData/RawData/AllupperairVcomponent.txt");
      ArrayList a1 = new ArrayList();
      BufferedReader br = new BufferedReader(file);
      String line = "";
      while ((line = br.readLine()) != null) {
        a1.add(line);
      }
    } catch (Exception e) {
      // TODO: handle exception
      e.printStackTrace();
    }
  }

【问题讨论】:

  • 不想将 300MB 的数据放入内存中?或者,如果您确实需要,请使用 -Xmx 标志增加允许的最大 java(堆)内存。
  • 如果您没有足够的内存来加载它,您将需要逐步处理数据。您预计 300 MB 将使用大约 800 MB 的内存,因为您的 ArrayList 和 Strings 有开销并且每个字符使用两个字节。

标签: java


【解决方案1】:

天真地,通过 Xmx 命令行参数增加堆的大小(请参阅此excellent answer 以获得一些指导)

不过,这只能在一定程度上起作用,而是考虑构建数据结构,以最大限度地减少内存需求。您是否需要一次将所有内容都保存在内存中?也许您只需要测试一个项目是否在该集合中,考虑使用散列或布隆过滤器(等)。

【讨论】:

  • 当我尝试打印行时,它很容易打印,但是当我尝试添加到数组列表中时,它会引发异常。
  • 你打算用这些字符串做什么?你想解决什么问题?
  • @user1730833 您的代码在这样的杂乱评论中不是很好,请编辑您的问题并将其添加到那里...
【解决方案2】:

只是增加Java的堆大小

java -Xmx250m

如果您从 IDE 运行项目,请在参数中设置 -Xmx250m。

250m 等于 250mb

【讨论】:

    【解决方案3】:

    如果您必须将它放在内存中,您可以尝试通过将-mx 选项传递给java 可执行文件来增加堆大小。

    如果您真的需要同时在内存中存储所有数据,那么这个问题可能也值得考虑。您可以按顺序处理它,也可以将其大部分或全部保存在磁盘上。

    【讨论】:

    • 现在一个 300MB 的文件是否大到可以在内存中一次性读取?
    • @Cratylus:我认为您的问题除了“视情况而定”之外没有明显的答案。此外,完全不清楚该解决方案是否需要超过 300MB,如果需要,超出多少。
    • @Cratylus 对于 64 位 JVM,它并不多,但对于 32 位 JVM,它可能是。如果它是磁盘上 300 MB 的 8 位文本,当您在 Java 中将其作为字符串读入时,它会立即扩展为 600 MB 的 UTF-16 字符。然后在这些原始数据之上,您将拥有数据结构开销,这可能是每行至少 10-20 个字节,具体取决于数据结构。所以它开始加起来......
    • 告诉我读取文件然后将内容添加到arraylist的优化方式。
    【解决方案4】:

    通过 -Xmx1024m 将堆空间增加到 1024 mb。

    java -Xms1024m -Xmx512m HelloWorld
    

    在 32 位系统上最多可以增加 4GB,而在 64 位系统上可以更高。

    【讨论】:

      【解决方案5】:

      使用 java.nio.file.Files.readAllLines,它会返回 List<String>. 如果您遇到 OOME,请将堆大小增加为 java -Xmx1024m

      【讨论】:

        【解决方案6】:

        我部分同意@Murali,这将解决您面临的问题。但建议在处理大文件时使用缓存。如果文件大小在极少数情况下变为 500Mb 怎么办。使用像 Memcached 这样的缓存 API,这将消除 JVM 中的内存中断。

        【讨论】:

          【解决方案7】:

          如果可以的话:分批处理 10000 行左右的文件。

          读取 10k 行 过程 重复直到完成

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-27
            • 2017-08-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多