SetUniqueList,HashSet和Set不会从对象的List中删除重复项

时间:2015-01-03 02:34:24

标签: java

我一直想做的是对List中的对象进行排序,并从同一个List中删除重复的对象。

这是对象的类

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”实例,我一直在尝试从此列表中删除重复项。

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

  1. SetUniqueList

    List<Word> NoDup = SetUniqueList.setUniqueList(WordsListWithNumber);
    
  2. HashSet的

    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);
    
  4. 我已经确认所有这些方法都可以从“String”列表中删除重复项,但它似乎没有从此类的List中删除重复项。

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

        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。

    我意识到“数字”属性应该被命名为“数量”......似乎有些人认为这个“数字”属性类似于ID号,但它实际上表明了多少相同的单词“WordsList” “包含。

    我想比较“wordname”,而不是“数字”。 抱歉令人困惑,我不是母语为英语的人。

1 个答案:

答案 0 :(得分:2)

如果要从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)
  5. 您已表明您的意思是3。

    指定重复项的含义的方法是重写equals方法。你可以这样做。

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

    每当您覆盖equals方法时,您还必须覆盖hashCode。 (搜索SO以获得解释)。

    以下是hashCode的可能Word方法。

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

    如果您执行此操作,您会发现如果listList<Word>,则可以通过编写

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

    有关如何编写equalshashCodecompareTo方法的详细信息(如果数字很大,您的compareTo方法可能会失败),我建议使用Java作者:Joshua Bloch。

    祝你好运!