我很好奇如何在不适合内存的数据上创建反向索引。所以现在我正在读取文件目录并根据文件内的内容索引文件,我使用HashMap来存储索引。下面的代码是我使用的函数的片段,我在整个目录上调用该函数。如果这个目录很大并且HashMap不能适合所有条目,我该怎么办?是的,这听起来像是过早优化。我只是玩得开心。我不想使用Lucene,所以甚至不要提及它,因为我很难看到这是“索引”的主要答案。这个HashMap是我唯一的约束,其他所有内容都存储在文件中,以便以后轻松引用。
我只是好奇我是如何做到这一点的,因为它将它存储在地图中就像这样
keyword -> file1,file2,file3,etc..(locations)
keyword2 -> file9,file11,file13,etc..(locations)
我的想法是创建一个文件,如何能够更新自己,就像上面的格式,但我觉得这不高效。
代码段
br = new BufferedReader(new FileReader(file));
while ((line = br.readLine()) != null) {
for (String _word : line.split("\\W+")) {
word = _word.toLowerCase();
if (!ignore_words.contains(word)) {
fileLocations = index.get(word);
if (fileLocations == null) {
fileLocations = new LinkedList<Long>();
index.put(word, fileLocations);
}
fileLocations.add(file_offset);
}
}
}
br.close();
更新
所以我设法得到了一些东西,但是表现明智我觉得这很慢,特别是如果有大量的数据。我基本上创建了一个文件,只需要在单词出现的每一行上都有单词和偏移量。让它命名为index.txt
。
它的格式是这样的
word1:offset
word2:offset
word1:offset <-encountered again.
word3:offset
etc...
然后我为每个单词创建了多个文件,并在每次在index.txt
文件中遇到时将偏移量附加到该文件。
所以基本上word文件的格式就是这样
word1.txt -- Format
word1:offset1:offset2:offset3:offset4...and so on
每次在index.txt
文件中遇到word1时,它会将其附加到word1.txt
文件并添加到结尾。
然后最后,我浏览了我创建的所有单词文件,并覆盖index.txt文件,索引文件中的最终输出看起来像这样
word1:offset1:offset2:offset3:offset4:...
word2:offset9:offset11:offset13:offset14:...
etc..
然后为了完成它,我删除了所有单词文件。
令人讨厌的代码片段如下,其数量相当可观。
public void createIndex(String word, long file_offset)
{
PrintWriter writer;
try {
writer = new PrintWriter(new FileWriter(this.file,true));
writer.write(word + ":" + file_offset + "\n");
writer.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
public void mergeFiles()
{
String line;
String wordLine;
String[] contents;
String[] wordContents;
BufferedReader reader;
BufferedReader mergeReader;
PrintWriter writer;
PrintWriter mergeWriter;
try {
reader = new BufferedReader(new FileReader(this.file));
while((line = reader.readLine()) != null)
{
contents = line.split(":");
writer = new PrintWriter(new FileWriter(
new File(contents[0] + ".txt"),true));
if(this.words.get(contents[0]) == null)
{
this.words.put(contents[0], contents[0]);
writer.write(contents[0] + ":");
}
writer.write(contents[1] + ":");
writer.close();
}
//This could be put in its own method below.
mergeWriter = new PrintWriter(new FileWriter(this.file));
for(String word : this.words.keySet())
{
mergeReader = new BufferedReader(
new FileReader(new File(word + ".txt")));
while((wordLine = mergeReader.readLine()) != null)
{
mergeWriter.write(wordLine + "\n");
}
}
mergeWriter.close();
deleteFiles();
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
public void deleteFiles()
{
File toDelete;
for(String word : this.words.keySet())
{
toDelete = new File(word + ".txt");
if(toDelete.exists())
{
toDelete.delete();
}
}
}