【问题标题】:Fast way to get different lines from 2 big files in Java [closed]从Java中的2个大文件中获取不同行的快速方法[关闭]
【发布时间】:2022-01-04 14:06:44
【问题描述】:

在 Java 中,我有一个读取两个文件的方法,每行都是一个 GUID。行是无序的。输出是两个新文件,其中的行仅出现在每个文件上。

示例文件:

| Input_1 | Input_2 |         | Output_1 | Output_2 |
| ------- | ------- |         | -------- | -------- |
| abcdef  | uvwxyz  |    >    | mnopqr   | uvwxyz   |
| ghijkl  | ghijkl  |
| mnopqr  | abcdef  |

我设法为每个文件使用了一个 Collection<String> 和一些 addAll() + removeAll() 恶作剧,但文件的大小正在增长,这整个过程现在需要一些时间。每个文件大约有 600k 行。

是否有一种仅使用另一种类型的集合来改进此代码的快速方法,或者我需要重构我的工作方式?

有问题的代码:

//Read two files
Collection<String> guidFile1 = readFileGuid(pathFile1);
Collection<String> guidFile2 = readFileGuid(pathFile2);

//Add file1 and remove file2
Collection<String> leftFromFile1 = new ArrayList<String>();
leftFromFile1.addAll(guidFile1);
leftFromFile1.removeAll(guidFile2);

//Add file2 and remove file1
Collection<String> leftFromFile2 = new ArrayList<String>();
leftFromFile2.addAll(guidFile2);
leftFromFile2.removeAll(guidFile1);

//Outputs
System.out.println("Leftover from file1: " + leftFromFile1.size());
System.out.println("Leftover from file2: " + leftFromFile2.size());

【问题讨论】:

  • 您为 Collection 接口使用了哪个实现?尝试 hashSet 而不是 List。
  • 这个社区更多的是关于“不工作”的代码。您宁愿对性能方面进行审查,所以codereview.stackexchange.com 可能是一个更好的地方。话虽如此,这里有很多方面。例如:顺序重要吗?如果你使用 Set 对象而不是 Lists,section/intersection 会更有效率。但是,您可能会丢失文件中的顺序。长话短说:最佳解决方案取决于您的具体要求。
  • 按顺序跟进:如果顺序无关紧要,您可以在从文件中读取列表后对列表进行排序。对 SORTED 内容进行这样的“增量”计算归结为以锁步方式迭代 2 个列表,仅一次,并避免例如调用 removeAll() 两次的开销。另请注意:排序是您甚至可以在文件中读取的内容,例如使用一些命令行调整。因此,如前所述:有很多选择,但根据您的具体情况,它们都会有所不同。
  • 如果文件无序,我会说您需要在文件 1 中创建一组 guid,然后检查文件 2 中存在哪些(您可以在此处使用流)。一种简单的方法是为文件 1 构建整个集合,然后处理文件 2。如果文件具有相似的顺序,您还可以尝试更复杂的方法,并行读取文件(例如较小的批次),但这可能会变得非常复杂.
  • @GhostCat 您对网站的看法完全正确,现在我感到有些羞耻。我不需要订单,只需要线条。这些文件一开始是无序的。

标签: java performance collections add removeall


【解决方案1】:

在您的代码中,removeAll 是最昂贵的操作。如果两个文件都是 100 行长,那么 removeAll 将执行 20,000 次操作。如果包含 addAll,那么它将执行总共 20,200 次操作。你想要的是 200 次操作。这样做的方法是使用 Set。

  static HashSet<String> readFileGuid(String path) throws IOException{
      HashSet<String> guidFile = new HashSet<>();
      Scanner s = new Scanner(new File(path));
      while(s.hasNextLine()) 
        guidFile.add(s.nextLine());
      s.close();
      return guidFile;
  }
  
  static List<String> subtract(HashSet<String> s1, HashSet<String> s2){
      List<String> result = new ArrayList<>();
      Iterator<String> it = s1.iterator();
      while(it.hasNext()){
          String item = it.next();
          if (!s2.contains(item))
            result.add(item);
      }
      return result;
  }
  
  public static void main (String[]args) throws IOException{
      HashSet<String> guidFile1 = readFileGuid("input1.txt");
      HashSet<String> guidFile2 = readFileGuid("input2.txt");
      
      List<String> leftFromFile1 = subtract(guidFile1, guidFile2);
      List<String> leftFromFile2 = subtract(guidFile2, guidFile1);
      
      System.out.println("file1:" + leftFromFile1);
      System.out.println("file2:" + leftFromFile2);
  }

【讨论】:

    猜你喜欢
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    相关资源
    最近更新 更多