在Java中通过非常大的数组创建和解析

在Java中通过非常大的数组创建和解析,java,arrays,list,csv,memory-management,Java,Arrays,List,Csv,Memory Management,我有一个近200万行的CSV文件,有3列(项目、评级、用户)。我能够将数据传输到2D字符串数组或列表中。然而,当我试图解析数组以从中创建CSV文件时,我的问题就出现了,因为应用程序停止了,我不知道我需要等待程序完成运行多长时间 基本上,我的最终目标是能够解析大型CSV文件,创建一个矩阵,其中每个不同的项目代表一行,每个不同的用户代表一列,评级位于用户和项目的交叉点。通过这个矩阵,我创建了一个余弦相似性矩阵,其中行和列由项目表示,它们的余弦相似性位于两个不同项目的交点处 我已经知道如何创建CSV文

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

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

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

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

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

  • 获取大型CSV文件
  • 通过大型CSV文件进行解析
  • 创建类似原始CSV文件的二维数组
  • 创建不同项的列表(每个不同项由一个索引号表示)
  • 创建不同用户的列表(每个不同用户由一个索引号表示)
  • 创建的二维数组,行索引表示项目,列索引表示用户,从而生成数组[行][列]=评级
  • 计算两个矩阵的余弦相似性
  • 创建二维数组,其中行和列索引表示生成数组[row]的项 [列]=余弦相似性
  • 我注意到我的程序在达到步骤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();
             }
          }
    
    FileInputStream=null;
    扫描器=空;
    试一试{
    stream=新文件输入流(文件名);
    扫描仪=新扫描仪(流,“UTF-8”);
    while(scanner.hasNextLine()){
    字符串行=scanner.nextLine();
    如果(!line.equals(“”){
    String[]elems=line.split(“,”);
    if(itemList.isEmpty()){
    itemList.add(elems[0]);
    }
    否则{
    如果(!itemList.contains(元素[0]))
    itemList.add(elems[0]);
    }
    if(nameList.isEmpty()){
    名称列表。添加(元素[2]);
    }
    否则{
    如果(!nameList.contains)(元素[2]))
    名称列表。添加(元素[2]);
    }
    for(int i=0;i
    您可以尝试设置。如果使用默认值,则可能只需要为JVM分配更多内存

    除此之外,您还可以修改代码,使其不会将所有内容都视为
    字符串
    。对于
    score
    列(可能是数字),您应该能够将其解析为数字值,并将其存储,而不是字符串表示。为什么?字符串使用的内存比数值多得多。即使是空字符串,也可以使用单个数值


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

    请在此处添加一个.im,说明内存有问题。垃圾收集器试图释放内存以继续,但没有得到内存。因此,使用-xmxjava参数增加heapspace。降低数据结构的内存占用。另一种可能是将您的CSV放入数据库(H2、Derby或大型数据库),并在那里进行数据查询。