私は私のTreeSetのために、以下のコンパレータがあります。
public class Obj {
public int id;
public String value;
public Obj(int id, String value) {
this.id = id;
this.value = value;
}
public String toString() {
return "(" + id + value + ")";
}
}
Obj obja = new Obj(1, "a");
Obj objb = new Obj(1, "b");
Obj objc = new Obj(2, "c");
Obj objd = new Obj(2, "a");
Set<Obj> set = new TreeSet<>((a, b) -> {
System.out.println("Comparing " + a + " and " + b);
int result = a.value.compareTo(b.value);
if (a.id == b.id) {
return 0;
}
return result == 0 ? Integer.compare(a.id, b.id) : result;
});
set.addAll(Arrays.asList(obja, objb, objc, objd));
System.out.println(set);
これは、重複を除去[(1A)、(2C)]を、プリントアウト。
私が最後に変更されたときしかしInteger.compare
するInteger.compare(b.id, a.id)
(すなわち、Bの位置を切り換え)、これは、[(2A)、(1A)、(2C)]プリントアウト。明らかに同じid 2回登場しました。
あなたはいつもにコンパレータをどのように修正すればよいのIDに基づいて重複を削除し、ソート値(昇順)そして、ID(降順)に基づく順序集合?
あなたはしていaskimg:
どのようにあなたが常にIDに基づいて重複を削除し、ソート値(昇順)そして、ID(降順)に基づく順序セットにコンパレータを修正するのですか?
あなたは、比較がしたいです
- 削除重複に基づきます
Obj.id
- でセットを並べ替える
Obj.alue
と、Obj.id
要件1)の結果で
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
要件2)の結果で
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
のは、上を見てみましょうのJavaDocのをTreeSet
。それは言います:
順序が設定することによって維持することを注意[...]と一致している必要があり
equals
、それは正しく実装している場合はSet
インターフェイスを。これがそうであるSet
インタフェースがに関して定義されたequals
動作が、TreeSet
インスタンスを行う全ての素子の比較は、その使用compareTo
(または比較)方法を、この方法によって等しいと見なされるので、2つの要素がセットの観点から、ある等しいです。
セットには、コンパレータに従って順序付けされますが、その要素もコンパレータを使用して等しいかどうかを比較しています。
私の知る限り見ることができるように定義する方法がありませんComparator
その両方を満たす要件を。以来、TreeSet
最初の場所にあるSet
必要1)と一致しなければなりません。要件2を達成するために)あなたは、第二を作成することができますTreeSet
。
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
それとも、セット自体は必要ありませんが、あなたが使用することができ所望の順序で要素を処理する場合Stream
:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
ところで:
それはの要素をソートすることも可能ですがStream
与えられたに応じてComparator
何が無いdistinct
服用方法Comparator
、それに応じて重複を削除します。
EDIT:
1.重複除去、2ソート:次の2つの異なるタスクを持っています。一つは、Comparator
両方のタスクを解決することはできません。だから、選択肢があり何ですか?
あなたは無効にすることができますequals
し、hashCode
上Obj
。その後、HashSet
またはStream
重複を除去するために使用することができます。
並べ替えのためにあなたはまだ必要ですComparator
(上記のように)。実装Comparable
だけによる「equalsと一貫性」ではありません発注につながるソートするためComparable
のJavaDoc。
以来Stream
、両方のタスクを解決することができ、それは私の選択です。まず、上書きhashCode
とequals
で重複を識別するためにid
:
public int hashCode() {
return Integer.hashCode(id);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Obj other = (Obj) obj;
if (id != other.id)
return false;
return true;
}
今、私たちは使用することができますStream
:
// instantiating one additional Obj and reusing those from the question
Obj obj3a = new Obj(3, "a");
// reusing sortingComparator from the code above
Set<Obj> set = Stream.of(obja, objb, objc, objd, obj3a)
.distinct()
.sorted(sortingComparator)
.collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println(set); // [(3a), (1a), (2c)]
返されたLinkedHashSet
の意味を持っているSet
が、それはまたの順序を保存しますsortingComparator
。
EDIT(コメントからの質問に答えます)
Q:なぜ、それは正しく仕事を完了しませんでしたか?
自分自身でそれを参照してください。あなたの最後の行に変更しComparator
、以下のように
int r = result == 0 ? Integer.compare(a.id, b.id) : result;
System.out.println(String.format("a: %s / b: %s / result: %s -> %s", a.id, b.id, result, r));
return r;
一度コードを実行し、その後のオペランドを切り替えますInteger.compare
。スイッチは、別の比較経路をもたらします。とき違いがある(2a)
と(1a)
比較されます。
最初の実行では(2a)
より大きく、(1a)
それは次のエントリと比較していますので(2c)
。平等でこの結果-重複が発見されました。
セカンドランでは(2a)
より小さくなります(1a)
。したがって(2a)
、以前のエントリと次のように比較されます。しかし、(1a)
すでに最小のエントリで、以前の1はありません。したがって、重複が見つかりません(2a)
、それがセットに追加されます。
Q:あなたは、1個のコンパレータを2つのタスクを完了することはできません、実際には私の第一のコンパレータが正しく両方のタスクをしたと述べました。
はい-だけ与えられた例。追加Obj obj3a
私が行ったようにセットにし、あなたのコードを実行します。返されるソートセットは次のとおりです。
[(1a), (3a), (2c)]
これは同じのためにソートするためにあなたの条件に違反したvalue
ことにより、降順秒id
。今ではで昇順ですid
。私のコードを実行し、上記のように、それは、正しい順序を返します。
苦しんでComparator
、私は次のコメントを得た前の時間:「...それは手動のコンパレータの実装がいかに難しい実証し、偉大な運動だ...」(ソース)