从 Java 中的 2 个大文件中获取不同行的快速方法
Fast way to get different lines from 2 big files in Java
在Java中,我有一个读取两个文件的方法,每行都是一个GUID。行是无序的。输出是两个新文件,其中的行仅出现在每个文件中。
示例文件:
| Input_1 | Input_2 | | Output_1 | Output_2 |
| ------- | ------- | | -------- | -------- |
| abcdef | uvwxyz | > | mnopqr | uvwxyz |
| ghijkl | ghijkl |
| mnopqr | abcdef |
我成功地完成了每个文件一个 Collection<String>
和一些 addAll()
+ removeAll()
恶作剧,但是文件的大小越来越大,这整个过程需要一些时间是时候了。每个文件大约有 60 万行。
是否有仅使用另一种类型的集合来快速改进此代码的方法,或者我需要重构我的做法?
有问题的代码:
//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());
在您的代码中,removeAll
是最昂贵的操作。如果两个文件都是 100 行长,那么 removeAll
将执行 20,000 次操作。如果您包括 addAll,那么它将执行总共 20,200 次操作。你想要的是 200 次操作。这样做的方法是使用一个集合。
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);
}
在Java中,我有一个读取两个文件的方法,每行都是一个GUID。行是无序的。输出是两个新文件,其中的行仅出现在每个文件中。
示例文件:
| Input_1 | Input_2 | | Output_1 | Output_2 |
| ------- | ------- | | -------- | -------- |
| abcdef | uvwxyz | > | mnopqr | uvwxyz |
| ghijkl | ghijkl |
| mnopqr | abcdef |
我成功地完成了每个文件一个 Collection<String>
和一些 addAll()
+ removeAll()
恶作剧,但是文件的大小越来越大,这整个过程需要一些时间是时候了。每个文件大约有 60 万行。
是否有仅使用另一种类型的集合来快速改进此代码的方法,或者我需要重构我的做法?
有问题的代码:
//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());
在您的代码中,removeAll
是最昂贵的操作。如果两个文件都是 100 行长,那么 removeAll
将执行 20,000 次操作。如果您包括 addAll,那么它将执行总共 20,200 次操作。你想要的是 200 次操作。这样做的方法是使用一个集合。
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);
}