3

HashSet.add(Object obj)更新:は呼び出されないと思いますcontains。私が欲しいものを実装する方法はありますか (dup 文字列を削除し、ケースを使用して大文字と小文字を無視しSetます)?

元の質問: Java で文字列のリストから重複を削除しようとしていますが、次のコードCaseInsensitiveSet.contains(Object ob)では呼び出されません。なぜですか?

public static List<String> removeDupList(List<String>list, boolean ignoreCase){
    Set<String> set = (ignoreCase?new CaseInsensitiveSet():new LinkedHashSet<String>());
    set.addAll(list);

    List<String> res = new Vector<String>(set);
    return res;
}


public class CaseInsensitiveSet  extends LinkedHashSet<String>{

    @Override
    public boolean contains(Object obj){
        //this not getting called.
        if(obj instanceof String){

            return super.contains(((String)obj).toLowerCase());
        }
        return super.contains(obj);
    }

}
4

5 に答える 5

7

試す

        Set set = new TreeSet(String.CASE_INSENSITIVE_ORDER);
        set.addAll(list);
        return new ArrayList(set);

更新しますが、Tom Anderson が述べたように、最初の順序は保持されません。これが本当に問題である場合は、試してみてください

    Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
    Iterator<String> i = list.iterator();
    while (i.hasNext()) {
        String s = i.next();
        if (set.contains(s)) {
            i.remove();
        }
        else {
            set.add(s);
        }
    }

版画

[2, 1]
于 2012-12-26T12:09:53.020 に答える
5

containsLinkedHashSet がそのように実装されていないため、呼び出されません。

add() で contains() を呼び出したい場合は、それもオーバーライドする必要があります。

このように実装されていない理由は、contains を最初に呼び出すと、検索が 1 回ではなく 2 回実行されるため、処理が遅くなるためです。

于 2012-12-26T12:08:23.860 に答える
3

add()のメソッドを内部的にLinkedHashSet呼び出さないでください。そうしないとcontains()、メソッドも呼び出されます。

の代わりに、大文字と小文字を区別しないコンパレータLinkedHashSetを使用しないのはなぜですか? String.CASE_INSENSITIVE_ORDERコンパレータSortedSetを使用

あなたのコードは

public static List<String> removeDupList(List<String>list, boolean ignoreCase){
    Set<String> set = (ignoreCase?new TreeSet<String>(String.CASE_INSENSITIVE_ORDER):new LinkedHashSet<String>());
    set.addAll(list);

    List<String> res = new ArrayList<String>(set);
    return res;
}

@tom anderson が彼のコメントで指定したように、注文を保持したい場合は、注文に補助的な LinkedHashSet を使用できます。

true を返す場合は、その要素を TreeSet に追加してみることもできます。そうでない場合は、LinkedHashSet にも追加します。

public static List<String> removeDupList(List<String>list){
        Set<String> sortedSet = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
        List<String> orderedList = new ArrayList<String>();
        for(String str : list){
             if(sortedSet.add(str)){ // add returns true, if it is not present already else false
                 orderedList.add(str);
             }
        }
        return orderedList;
    }
于 2012-12-26T12:18:20.690 に答える
0

試す

    public boolean addAll(Collection<? extends String> c) {
            for(String s : c) {
            if(! this.contains(s)) {
                this.add(s);
            }
        }
        return super.addAll(c);
    }
    @Override
    public boolean contains(Object o) {
        //Do your checking here
//      return super.contains(o);
    }

これにより、コードを通過させたい場合は、contains メソッドが確実に呼び出されます。

于 2012-12-26T12:34:30.540 に答える
0

重複排除のために文字列を使用する別のアプローチをHashSet次に示しますが、結果リストを直接作成します。

public static List<String> removeDupList(List<String> list, boolean ignoreCase) {
    HashSet<String> seen = new HashSet<String>();
    ArrayList<String> deduplicatedList = new ArrayList<String>();
    for (String string : list) {
        if (seen.add(ignoreCase ? string.toLowerCase() : string)) {
            deduplicatedList.add(string);
        }
    }
    return deduplicatedList;
}

これは非常に単純で、要素を 1 回だけパスし、小文字、ハッシュ検索、および各要素のリストの追加のみを行います。

于 2012-12-26T13:31:22.367 に答える