Иметь эффективное отношение многие ко многим в Java - PullRequest
1 голос
/ 10 марта 2010

Как сделать эффективную many-to-many -отношение от fileID до Words и от word до fileIDs без инструментов базы данных, таких как Postgres в Java?

У меня есть следующие классы. Отношение от fileID до words дешево, но не наоборот, так как для этого мне нужны три for -петля.

альтернативный текст http://img191.imageshack.us/img191/4077/oliorakenne1.png

Мое решение неэффективно. Другими вариантами может быть создание дополнительного класса с word в качестве идентификатора с ArrayList из fileID с.

Ответ на ответ 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 в паста .

Ответы [ 3 ]

1 голос
/ 10 марта 2010

Оба класса должны переопределять hashCode и равно. Таким образом, вы решите, что равно.

Затем вы создадите набор в каждом из ваших классов.

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

1 голос
/ 10 марта 2010

Не будет ли более эффективным подход назначить ссылку из Word на MyFile в тот момент, когда вы знаете, что 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.

Изменено после добавления кода, который составляет список слов:

Хорошо, поэтому, увидев код, который строит ваши Слова, я не думаю, что установление отношений является источником вашей неэффективности. Похоже, что вы устанавливаете отношения точно так, как я предложил (добавляя каждое слово, вы присваиваете этому файлу идентификатор файла соответствующего файла).

Похоже, источником вашей неэффективности является то, что для каждого слова вы должны сопоставлять его с различными вещами, которые у вас есть в наборе файлов (например, WordToWordId). Таким образом, для каждого слова вам нужно пройтись по каждой строке этого файла и найти соответствие. Это, конечно, неэффективно.

Лучшим подходом является размещение этих пар в памяти в HashMap, инициализированных при запуске. Таким образом, если у вас есть определенное слово и вам нужен соответствующий идентификатор, или наоборот, вы ищите их в своей HashMap, которая является операцией постоянного времени. Точно так же для каждого слова вы просматриваете каждый файл; снова сделайте этот цикл ОДИН РАЗ и сохраните результат в HashMap. Тогда поиски становятся постоянными.

0 голосов
/ 10 марта 2010

Я думаю, вы хотите, чтобы файл знал свои слова, а слова знают файлы, в которых он используется.

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 Design. Возможно, ваш тип данных неверен (я не говорю неправильно, потому что это ваш дизайн, поэтому я уважаю).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...