2017-09-28 12 views
0

Je suis (j'essayais) de créer une LinkedList qui supprime les doublons lors de l'insertion. Ceci est mon code:Aucun doublon après l'insertion

LinkedList<WordInDocument> list = new LinkedList<WordInDocument>(); 
/** 
* Insert a word. 
* 
* @param insertWord The word that'll be inserted for, the word and it's Part Of Speech. 
* If you print "insertWord.word" you'll get the String of the word. 
*/ 
public void insert (Word insertWord) { 
    ListIterator<WordInDocument> listIt = list.listIterator(); 
    WordInDocument entry = new WordInDocument(insertWord); 
    if (list.isEmpty()) { 
     listIt.add(entry); 
    } 
    else { 
     while (listIt.hasNext()) { 
      //the iterator iterate with this if-statment, 
      //if the iterator finds a equal word, then break 
      if (listIt.next().wordInEntry.word.equalsIgnoreCase(insertWord.word)) { 
       break; 
      } 
     } 
     //only true if an equal word wasn't found, then ad the word at the end 
     if (!listIt.hasNext()) { 
      listIt.add (entry); 
     } 
    } 
} 

Mais si c'est beaucoup d'entrées, alors il faut beaucoup de temps pour exécuter cette (environ 1 minute). Est-ce leur meilleur moyen de supprimer les valeurs en double lors de l'insertion?

EDIT:
Merci pour l'aide. Je l'ai résolu en utilisant "insertion binaire" comme je l'appelle. De cette façon, il est également trié après chaque insertion que j'ai voulu faire après la dernière insertion. Voici mon code:

WordInDocument[] list = new WordInDocument[MAX_INDEX]; 
int currentMaxIndex = 0; 
/** 
* Insert a word, it uses binary search to find where to put it, if the 
* current word dosn't exists, then insert it, this can bee called "Binary insert". 
* If the current word already exists, then ignore. 
* 
* @param insertword The word that'll be inserted for, the word and it's Part Of Speech. 
* If you print "insertWord.word" you'll get the String of the word. 
*/ 
public void insert(Word insertword) { // put element into array 
    WordInDocument entry = new WordInDocument(insertword); 
    //First element 
    if (list[0] == null) { 
     list[0] = entry; 
     currentMaxIndex++; 
     return; 
    } 
    int inputIndex = binaryInsert(insertword); 
    //It's at the end 
    if (list[inputIndex] == null) { 
     list[inputIndex] = entry; 
     currentMaxIndex++; 
     return; 
    } 
    //It's equal to another word 
    if (list[inputIndex].wordInEntry.word.equalsIgnoreCase(word.word)) { 
     return; 
    } 
    //It's between two entries 
    for (int i = currentMaxIndex; i > inputIndex; i--) { // move bigger ones one up. 
     list[i] = list[i - 1]; 
    } 
    list[inputIndex] = entry; 
    currentMaxIndex++; 
} 

private int binaryInsert(Word word) { 
    int lowerBound = 0; 
    int upperBound = currentMaxIndex - 1; 
    int compareStrings = list[mid].wordInEntry.word.compareToIgnoreCase(word.word); 
    while (true) { 
     int mid = (upperBound + lowerBound)/2; 
     if (lowerBound == mid) { 
      if (compareStrings > 0) { 
       return mid; 
      } 
     } 
     if (compareStrings < 0) { 
      lowerBound = mid + 1; // its in the upper 
      if (lowerBound > upperBound) { 
       return mid += 1; 
      } 
     } else if (lowerBound > upperBound) { 
      return mid; 
     } else { 
      upperBound = mid - 1; // its in the lower 
     } 
    } 
} 

Maintenant, cela prend 2 secondes au lieu de 45 secondes.

+1

Pourquoi ne pas simplement utiliser un 'set'? – Kayaman

+5

Utilisez simplement 'LinkedHashSet'. – lexicore

+0

avec un ensemble ou une autre structure de données n'oubliez pas d'implémenter le hashcode et est égal à des types non primitifs – Frank

Répondre

0

Si vous souhaitez toujours utiliser une structure de données LinkedList (pas Set) et le faire avec Java8, ici il est une solution facile et plus rapide:

LinkedList<WordInDocument> list = new LinkedList<>(); 

public void insert (WordInDocument insertWord) { 
    // try to find any matching element 
    Optional<WordInDocument> optionalExistingWord = 
     list 
     .stream() 
     .parallel() 
     .filter(element -> element.word.equalsIgnoreCase(insertWord.word)) 
     .findAny(); 
    // if none is found, add the new element to the list 
    if(!optionalExistingWord.isPresent()) { 
     list.add(insertWord); 
    } 
} 
0

Vous pouvez supprimer les doublons via TreeSet:

LinkedList<WordInDocument> list = new LinkedList<>(); 
    TreeSet<WordInDocument> set = new TreeSet<>(
      new Comparator<WordInDocument>() { 
       @Override 
       public int compare(WordInDocument d1, WordInDocument d2) { 
        return d1.word.compareToIgnoreCase(d2.word); 
       } 
      }); 
    set.addAll(list); 
    list = new LinkedList<WordInDocument>(set); 

cela devrait être plus rapide