【问题标题】:Creating and Parsing Through Very Large Arrays in Java在 Java 中创建和解析非常大的数组
【发布时间】:2020-01-31 08:25:07
【问题描述】:

我有一个包含近 200 万行和 3 列(项目、评级、用户)的 CSV 文件。我能够将数据传输到二维字符串数组或列表中。但是,当我尝试解析数组以从中创建 CSV 文件时出现了我的问题,因为应用程序停止并且我不知道我需要等待多长时间才能等待程序完成运行。

基本上,我的最终目标是能够解析大型 CSV 文件,创建一个矩阵,其中每个不同的项目代表一行,每个不同的用户代表一列,评分位于用户和项目的交叉点。使用这个矩阵,然后我创建一个余弦相似度矩阵,其中行和列由项目表示,它们的余弦相似度位于两个不同项目的交点。

我已经知道如何创建 CSV 文件,但是在创建其他数组以进行比较时,我的问题属于大型循环结构。

有没有更好的方法来处理和计算大量数据,以免我的应用程序冻结?

我当前的程序执行以下操作:

  1. 获取大型 CSV 文件
  2. 通过大型 CSV 文件进行解析
  3. 创建类似于原始 CSV 文件的二维数组
  4. 创建不同项目的列表(每个不同的项目由索引号表示)
  5. 创建不同用户列表(每个不同用户由索引号表示)
  6. 创建 2D 数组,其中行索引表示项目,列索引表示用户,结果数组 [row][column] = rating
  7. 计算两个矩阵的余弦相似度
  8. 创建二维数组,其中行索引和列索引表示项,从而导致数组 [行] [列] = 余弦相似度

我注意到我的程序在执行第 4 步和第 5 步时冻结 如果我删除第 4 步和第 5 步,它仍会在第 6 步冻结

我已经附上了我的那部分代码

      FileInputStream stream = null;
      Scanner scanner = null;

      try{
         stream = new FileInputStream(fileName);
         scanner = new Scanner(stream, "UTF-8");
         while (scanner.hasNextLine()){
             String line = scanner.nextLine();
             if (!line.equals("")){
                String[] elems = line.split(",");
                if (itemList.isEmpty()){
                  itemList.add(elems[0]);
                }
                else{
                  if (!itemList.contains(elems[0]))
                     itemList.add(elems[0]);
                }
                if (nameList.isEmpty()){
                  nameList.add(elems[2]);
                }
                else{
                  if (!nameList.contains(elems[2]))
                     nameList.add(elems[2]);
                }
                for (int i = 0; i < elems.length; i++){
                   if (i == 1){
                     if (elems[1].equals("")){
                        list.add("0");
                      }
                      else{
                        list.add(elems[1]);
                      }
                   }
                   else{
                     list.add(elems[i]);
                   }
                }
             }
         } 
         if (scanner.ioException() != null){
            throw scanner.ioException();
         }
      }
      catch (IOException e){
         System.out.println(e);
      }
      finally{
         try{
            if (stream != null){
               stream.close();
            }
         }
         catch (IOException e){
            System.out.println(e);
         }
         if (scanner != null){
            scanner.close();
         }
      }

【问题讨论】:

  • 恕我直言,您在这里遇到了内存问题。垃圾收集器尝试释放内存以继续,但没有得到。所以使用 -Xmx java 参数增加你的堆空间。降低数据结构的内存占用。另一种可能性是将您的 CSV 放入数据库(H2、Derby 或大型数据库)并在那里进行数据查询。

标签: java arrays list csv memory-management


【解决方案1】:

您可以尝试设置-Xms and -Xmx。如果您使用默认值,则可能只需要为 JVM 分配更多内存。

除此之外,您可以修改您的代码,使其不会将所有内容都视为String。对于score 列(可能是数字),您应该能够将其解析为数字值并存储它而不是字符串表示形式。为什么?字符串比数值使用更多的内存。即使是 字符串 uses 40 bytes,而单个数值可以是 as little as one byte

如果单个 byte 可以工作(数值范围是 -128 到 127),那么您可以用 ~2MB 替换 ~80MB 内存使用量。即使使用int(4 字节)也会比String 有很大的改进。如果数据中存在任何其他数字(或布尔)值,您可以进一步减少。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-28
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2022-06-10
    • 2010-09-26
    相关资源
    最近更新 更多