SetUniqueList、HashSet 和 Set 不会从对象列表中删除重复项

SetUniqueList, HashSet and Set don't remove duplicates from a List of an object

我一直在尝试做的是对列表中的对象进行排序,并从同一个列表中删除重复的对象。

这里是对象的class

public class Word implements Comparable<Word>{

private String wordName;
private int number;

 // There are only simple constructers, getters and setters 

 // This compareTo might be irrelevant for this question
@Override
public int compareTo(Word word) {
    int compareNumber = ((Word) word).getNumber();
    return compareNumber - this.number;

    }
}

这是主要方法的一部分

public class CommentEvaluationTester {
 final static private List<String> WordsList = new ArrayList<>();

 public static void main(String[] args) {

    boolean isContained;
    String comment = "";
    //This "comment" actually has a long string value
        for (String word : WordsInDB) {
        //WordsInDB is a List, containing String values

        isContained = comment.toLowerCase().contains(word.toLowerCase());
        if (isContained) {
            WordsList.add(word);
        }
    }

     List WordsListWithNumber = new ArrayList<>();

     for (String word : WordsList) {
            int occurrences = Collections.frequency(WordsList, word);

            Word addWord = new Word(word, occurrences);
            WordsListWithNumber.add(addWord);

     }

     //This might be irrelevant too   
     Collections.sort(WordsListWithNumber, new Comparator<Word>() {
            @Override
           public int compare(Word w1, Word w2) {
                return w2.getNumber() - w1.getNumber();
            }
        });

在这个阶段,"WordsListWithNumber" 列表包含多个 "Word" 实例,我一直在尝试从该列表中删除重复项。

我在 Whosebug 上找到了几种方法。

  1. SetUniqueList

    List<Word> NoDup = SetUniqueList.setUniqueList(WordsListWithNumber);
    
  2. 哈希集

    HashSet hs = new HashSet();
        hs.addAll(WordsListWithNumber);
        WordsListWithNumber.clear();
        WordsListWithNumber.addAll(hs);
    
  3. 设置

    Set<Word> noDupSet = new LinkedHashSet<Word>(WordsListWithNumber);
       List<Word> noDup = new ArrayList<>();
       noDup.addAll(noDupSet);
    

我已经确认所有这些方法都可以从 "String" 的列表中删除重复项,但似乎无法从 class.[=16= 的列表中删除重复项]

我通过这样做检查了列表的内容...但是它们都显示相同的值。

    Word testWord = (Word) noDup.get(0);
    System.out.println("test1: noDup.get(0) : " + testWord.getWordName() + " , number : " + testWord.getNumber());
    testWord = (Word) noDup.get(1);
    System.out.println("test2: noDup.get(1) : " + testWord.getWordName() + " , number : " + testWord.getNumber());

如果你能提供任何见解,我将不胜感激。

P.S.

我意识到"number"属性应该命名为"quantity"...好像有人认为这个"number"属性是身份证号码之类的东西,但实际上它表示"WordsList" 包含多少个相同的词。

我想比较 "wordname",而不是 "number"。 抱歉造成混淆,我的母语不是英语。

如果您想从 List 中删除重复项,您需要指定何时将两个项目视为重复项。指定很重要,因为在您的情况下,对于 word1word2 重复的含义至少有 4 种可能的解释:

  1. word1 == word2.
  2. word1.number == word2.number
  3. word1.wordName.equals(word2.wordName)
  4. word1.number == word2.number && word1.wordName.equals(word2.wordName)

你已经表明你的意思是 3。

指定重复的方式是覆盖 equals 方法。您可以按如下方式进行。

@Override
public boolean equals(Object object) {
    return object instanceof Word && ((Word) object).wordName.equals(wordName);
}

无论何时覆盖 equals 方法,您都必须同时覆盖 hashCode。 (搜索 SO 以获取对此的解释)。

这是 Word 的一种可能的 hashCode 方法。

@Override
public int hashCode() {
    return wordName.hashCode(); 
}

如果你这样做你会发现如果list是一个List<Word>,你可以通过写

来删除重复项
list = new ArrayList<Word>(new LinkedHashSet<Word>(list));

有关如何编写 equalshashCodecompareTo 方法的完整详细信息(如果数字很大,您的 compareTo 方法可能会失败),我推荐Joshua Bloch 的书 Effective Java。

祝你好运!