在Java中实现有效的多对多关系

时间:2010-03-10 14:37:35

标签: java many-to-many data-structures

如何在没有像Postgres这样的数据库工具的情况下,从many-to-manyfileID以及从Wordsword实现高效fileIDs关联在Java?

我有以下课程。 从fileIDwords的关系很便宜,但并非相反,因为我需要三个for -loops。

alt text http://img191.imageshack.us/img191/4077/oliorakenne1.png

我的解决方案显然效率不高。 其他选项可能是创建一个额外的类,word作为ArrayList fileID的ID。

回复JacobM的回答

MyFile的构造函数的相关部分是:

            /**
             * Synopsis of data in wordToWordConutInFile.txt:
             * fileID|wordID|wordCount
             *
             * Synopsis of the data in the file wordToWordID.txt:
             * word|wordID
             **/        


    /**
     * Getting words by getting first wordIDs from wordToWordCountInFile.txt and then words in wordToWordID.txt.
     */
    InputStream in2 = new FileInputStream("/home/dev/wordToWordCountInFile.txt");
    BufferedReader fi2 = new BufferedReader(new InputStreamReader(in2));

    ArrayList<Integer> wordIDs = new ArrayList<Integer>();
    String line = null;
    while ((line = fi2.readLine()) != null) {
        if ((new Integer(line.split("|")[0]) == currentFileID)) {
            wordIDs.add(new Integer(line.split("|")[6]));
        }
    }
    in2.close();

    // Getting now the words by wordIDs.
    InputStream in3 = new FileInputStream("/home/dev/wordToWordID.txt");
    BufferedReader fi3 = new BufferedReader(new InputStreamReader(in3));

    line = null;
    while ((line = fi3.readLine()) != null) {
        for (Integer wordID : wordIDs) {
            if (wordID == (new Integer(line.split("|")[1]))) {
                this.words.add(new Word(new String(line.split("|")[0]), fileID));
                break;
            }
        }
    }
    in3.close();

    this.words.addAll(words);

Word的构造函数位于the paste

3 个答案:

答案 0 :(得分:1)

在您知道Word在文件中时,更有效的方法是不是将Word中的链接分配给MyFile吗?也就是说,如何在MyFile对象中构建单词列表?如果您正在读取文件系统中的文件中的文件,而不是读取每个单词中的文件,则将其MyFile分配给当前文件。

//within MyFile constructor or setter for Words
while (//there's another word to add) {
   Word newWord = new Word(//read word from file);
   words.add(newWord);
   newWord.setMyFile(this);
}

这类似于管理双向父子关系的典型方法:

//in Parent
public void addChild(Child child) {
   myChildren.add(child);
   child.setParent(this);
}

如果您向我们展示如何构建MyFile对象,可能会有所帮助。

在您添加构建单词列表的代码后编辑:

好的,所以看到构建你的单词的代码,我不认为建立关系是你效率低下的根源。看起来你正在按照我建议的方式设置关系(当你添加每个单词时,你给这个单词指定相应文件的fileID)。

看起来效率低下的根源在于,对于每个单词,您必须将它与当前在一组文件中的各种内容(例如WordToWordId)进行匹配。因此,对于每个单词,您必须循环遍历该文件的每一行,并找到匹配项。这当然效率低下。

更好的方法是将这些配对放在HashMap的内存中,在启动时初始化。这样,如果你有一个特定的单词并需要相应的ID,反之亦然,你可以在你的HashMap中查找它,这是一个恒定时间的操作。同样,对于每个单词,您循环遍历每个文件;再次,执行循环ONCE,并将结果存储在HashMap中。然后查找成为恒定时间。

答案 1 :(得分:1)

两个类都应该覆盖hashCode和equals。因此,你将决定什么是平等的。

然后你将在每个班级中创建一个集合。

public class MyFile implements Comparable<MyFile> {
    //your fields here
    Set<Word> words = new HashSet<Word>(0);
    //Remember to override hashCode and equals
}

public class Word implements Comparable<Word> {
    //your fields here
    Set<MyFile> words = new HashSet<MyFile>(0);
    //Remember to override hashCode and equals
}

在你的套装中你现在将拥有所有的MyFiles.words和其他方面,所有的Words.myFile

答案 2 :(得分:0)

我认为你希望文件知道它的单词并且单词知道使用它的文件。

public class File {

private List<Word> words;
public File(){
words=new Vector<Word>();
}

/**
*The method add  word to word list.
**/
public addWord(Word word){
this.words.add(word);
word.addFile(this);
}
}
public class Word{
List<File> files;
public addFile(File file){
this.files.add(file);
}
}

反之亦然...但你应该质疑GRASP设计模式。也许你的数据类型是错误的(我不会说错,因为这是你的设计,所以我尊重)。