2010-03-10 4 views
1

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

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

alt text 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); 

Конструктор Слова на the paste.

ответ

1

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

Отредактирован после того, как вы добавили код, который строит список слов:

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

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

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

+0

Я добавил сборщиков MyFile к моему вопросу. –

+0

ОК, я вижу конструктор, но я до сих пор не вижу, где заполняется список слов. Это то, что меня интересует. –

+0

Спасибо, что указали это! Я добавил соответствующую часть конструктора к моему вопросу. –

1

Оба класса должны переопределять 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 и otherway вокруг, все Words.myFile

+0

Это также можно использовать в сочетании с тем, что @JacobM сказал –

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); 
} 
} 

или наоборот ... но вы должны задаться вопросом ГРАСП Design pattern.Maybe ваш тип данных неправильно (я не говорю неправильно, потому что ИТИС ваш DESING, поэтому я уважаю).

+0

Да, опечатка с моей стороны. Я исправил это сейчас –

Смежные вопросы