【问题标题】:No duplicates after insertion插入后没有重复
【发布时间】:2018-03-09 21:42:01
【问题描述】:

我(曾经)试图创建一个在插入过程中删除重复项的 LinkedList。这是我的代码:

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

但如果输入很多,则执行此操作需要很长时间(大约 1 分钟)。他们有更好的方法在插入期间删除重复值吗?

编辑:
谢谢您的帮助。我通过使用我所说的“二进制插入”来解决它。这样,它也会在每次插入之后进行排序,这是我在最后一次插入之后要做的。这是我的代码:

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

现在需要 2 秒而不是 45 秒。

【问题讨论】:

  • 为什么不直接使用Set
  • 只需使用LinkedHashSet
  • 使用 set 或其他数据结构不要忘记为非原始类型实现 hashcode 和 equals
  • insertWord 定义在哪里?
  • 如果重复最后一个元素,您的逻辑将失败。你应该return而不是break,并在末尾无条件插入。

标签: java sorting linked-list insert duplicates


【解决方案1】:

您可以通过 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);

这应该更快

【讨论】:

    【解决方案2】:

    如果您仍想使用LinkedList 数据结构(而不​​是Set)并使用Java8 执行此操作,这是一个简单快捷的解决方案:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 2019-10-20
      • 2013-01-07
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      相关资源
      最近更新 更多