3

私はこのようなJavaクラスを持っています

public class A {

    private String field1;
    private String field2;

    // getters, setters but no equals and hashcode
}

およびこのクラスのオブジェクトのリスト、同じフィールド1または同じフィールド2を持つすべての重複要素をこのリストから削除したいので、2つのコンパレーターがあります

public class Comparator1 implements Comparator<A> {
    public int compare(A o1, A o2) {

        return o1.getField1().compareToIgnoreCase( o2.getField1() );
    }
}

public class Comparator2 implements Comparator<A> {
    public int compare(A o1, A o2) {

        return o1.getField2().compareToIgnoreCase(o2.getField2());
    }
}

タスクを実行するには、ツリーセットを次のように使用します

TreeSet<A> ts1 = new TreeSet<A>(new Comparator1())
ts1.addAll(list)

TreeSet<A> ts2 = new TreeSet<A>(new Comparator2())
ts2.addAll(ts1)

list.clear()
list.addAll(ts2)

しかし、1つのコンパレータと1つのツリーセットだけを使用して同じことを行うにはどうすればよいですか?

助けてくれてありがとう

アップデート:

回答ありがとうございますが、それらを読んだ後、これが実際の問題に対する正しいアプローチであるかどうかわかりません。

私の実際のケースでは、field1 は電話番号のようなもので、field2 は名前のようなものです。したがって、同じ電話番号に複数回電話をかけたくありません (これは重複を削除する最初のツリーセットです)。同じ名前で複数回電話をかけたくありません (重複を削除する 2 番目のツリーセット)。

クラスを変更できますが、このアプローチで実際の問題を解決できるかどうかを知りたいです。

このアプローチが正しい場合、あなたの質問から、クラスを変更せずにコンパレータを1つだけ使用することはできないことがわかります

ありがとう

4

6 に答える 6

2

1つのコンパレータを使用して2つの基準で同時にソートすることはできないため、この場合、2つのTreeSetよりも優れた方法はありません。もちろん、それらを1つのデータ構造にラップすることもできます。

(または、2つのHashMapを使用して、それぞれに1つの文字列をキーとして使用することもできます。これは平均して高速ですが、プログラミングがより複雑になります。)

于 2011-04-09T00:29:33.367 に答える
1

あなたがやろうとしていることは明確に定義されているかどうかは私には明らかではありません。

現在のアプローチは、要素が追加される順序と、フィールド 1 またはフィールド 2 の重複を最初にチェックするかどうかの両方に依存することを認識していますか? 次のクラス A のオブジェクトがあるとします。

A ab = new A("a", "b");
A cb = new A("c", "b");
A cd = new A("c", "d");

最初に field1 をチェックすると、追加された順序に応じて結果[ab]またはが得られます。[ab, cd]

最初に field2 をチェックすると、追加された順序に応じて結果[cb]またはが得られます。[ab, cd]

これはかなり奇妙な動作です。これはあなたが意図したものですか?一般的なケースでは、単一の TreeSet と Comparator でこれを再現することはできないと思います。

于 2011-04-09T01:06:44.907 に答える
0
public static <A extends Comparable<?>>  TreeSet<A> getTreeSet(Collection<A> list){
    TreeSet<A> result = new TreeSet<A>();
    HashSet<A> unique = new HashSet<A>();
    unique.addAll(list);
    result.addAll(unique);
    return result;
}

アイテムをハッシュセットに追加して一意にし、TreeSetにドロップして並べ替える汎用関数。あなたはそれを一緒に使うことができます:TreeSet<A> ts1 = getTreeSet(list);

このアプローチは、固定リストに適しています。

@BalusCいいえ、これは

public class A implements Comparable<A> {

    private String field1;
    private String field2;

    @Override
    public int compareTo(A o) {
        // No null checks, because it's illegal anyways.
        int tmp = 0;
        if ((tmp = field1.compareToIgnoreCase(o.field1)) != 0)
            return tmp;
        if ((tmp = field2.compareToIgnoreCase(o.field2)) != 0)
            return tmp;
        return tmp;
    }
    // getters, setters but no equals and hashcode
}
于 2011-04-09T00:44:12.340 に答える
0

2 レベルの並べ替え (1 番目: PhoneNumber と 2 番目: 名前) を行う場合は、次のコードを使用できます。このコードでは、両方のフィールド (field1 と field2) に対して重複チェックが行われます。両方のフィールドにすでにcompareToを使用しているため、 equalshashcodeを使用する必要はありません。しかし、常にhashcodeequalsを使用することをお勧めします。

public class A implements Comparable<A> {

private String field1;
private String field2;

public A(String number, String name) {
    this.field1 = number;
    this.field2 = name;
}

// First level sorting will be done by field1. 
// If field1 is equal then second level sorting will be done on field2
@Override
public int compareTo(A o) {
    int compareTo = field1.compareTo(o.getNumber());
    if(compareTo==0){
        return field2.compareTo(o.getName());
    }
    return compareTo;
}

public String getNumber() {
    return field1;
}

public String getName() {
    return field2;
}

}

于 2014-05-27T08:00:00.480 に答える