我有一个包含文档索引和发布日期的文件:
0, 2012 - 05 - 26 t00:00:00z
1, 2012 - 05 - 26 t00:00:00z
2010 - 06 - 26 - t00:00:00z
2014 - 05 - 26 t00:00:00z
和第二个文本文件,其中包含术语频率和属于他的文档的索引:
为,15,1
杀死10 1
突尼斯,5,5
和平,1,0
我有这个方法匹配这两个文件,所以我可以用这个形式得到第三个文件:
was, 15, 2012-05-26T00:00:00Z
杀死10 2012 - 05 - 26 t00:00:00z
突尼斯,5,2010-06-26T00:00:00Z
和平,1,2012-05-26T00:00:00Z
我测试了一个测试文件的方法,它工作得很好,但我的文件大小是1T,所以我的程序已经执行了4天,仍然在工作。你能帮我优化一下或者给我另一种方法吗?
public void matchingDateTerme (String pathToDateFich, String pathTotermeFich) {
try {
BufferedReader inTerme = new BufferedReader(new FileReader(pathTotermeFich));
BufferedReader inDate = new BufferedReader(new FileReader(pathToDateFich));
String lineTerme,lineDate;
String idFich, idFichDate,dateterm,key;
Hashtable<String, String> table = new Hashtable<String, String>();
String[] tokens,dates;
Enumeration ID=null;
File tempFile = new File(pathTotermeFich.replace("fichierTermes", "fichierTermes_final"));
FileWriter fileWriter =new FileWriter(tempFile);
BufferedWriter writer = new BufferedWriter(fileWriter);
//read file date
while ((lineDate = inDate.readLine()) != null) {
dates = lineDate.split(", ");
idFichDate = dates[0].toLowerCase();
dateterm=dates[1];
table.put(idFichDate, dateterm);
}
while ((lineTerme = inTerme.readLine()) != null) {
tokens = lineTerme.split(", ");
idFich = tokens[2].toLowerCase();
String terme=tokens[0];
String freq=tokens[1];
//lire hachtable
ID = table.keys();
while(ID.hasMoreElements()) {
key = (String) ID.nextElement();
if(key.equalsIgnoreCase(idFich)){
String line=terme+", "+freq+", "+table.get(key);
System.out.println("Line: "+line);
writer.write(line);
writer.newLine();
}
}
}
writer.close();
inTerme.close();
inDate.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
您没有使用Hashtable
的实际用途:将键映射到值的对象
遍历键是无用且昂贵的,只需使用get
方法:
if (table.get(idFich) != null) {
String line = terme + ", " + freq + ", " + table.get(key);
System.out.println("Line: " + line);
writer.write(line);
writer.newLine();
}
正如VGR在评论中所说,使用不同步的HashMap
会更快。更多信息请点击
您应该使用https://en.wikipedia.org/wiki/Divide_and_conquer_algorithms方法与以下伪算法:
If A and B are your two large files
Open file A(1..n) for writing
Open file A for reading
for line in file A
let modulo = key % n
write line in file A(modulo)
Open file B(1..n) for writing
Open file B for reading
for line in file B
let modulo = key % n
write line in file B(modulo+1)
for i = 1..n
Open file R(i) for writing
Open files A(i) and B(i)
merge those files into R(i) using key matching as you do
Open file R for writing
for i = 1..n
append R(i) to R
尝试使用n = 1024,如果你的密钥是统一的,它将最终匹配1GB的文件
您需要磁盘上的空闲空间(如果不清理文件,则为A+B大小的三倍)
有两个注意事项。
- 这一定要在java中完成吗?如果是,在开始阅读文件之前,您能对文件进行排序吗?
- 你必须一次通过这些文件吗(高度怀疑)。如果没有,您应该将已排序的文件分成几个部分,并且只运行部分文件中条目的子集。
- 两个文件是否都超过1T?如果没有,您应该从较小的文件开始。
给file1:
0,2012-05-26T00:00:00Z
1,2012-05-26T00:00:00Z
5,2010-06-26T00:00:00Z
10,2014-05-26T00:00:00Z
和file2:
was,15,1
kill,10,1
tunisia,5,5
peace,1,0
下面是基于更新输入的基于awk的解决方案:
awk -F',' 'FNR==NR{a[$1]=$2;next}{if(a[$3]==""){a[$3]=0}; print $1,",",$2,",",a[$3]} ' file1 file2
输出:was , 15 , 2012-05-26T00:00:00Z
kill , 10 , 2012-05-26T00:00:00Z
tunisia , 5 , 2010-06-26T00:00:00Z
peace , 1 , 2012-05-26T00:00:00Z
这个答案对我推导上述解很有帮助。