あなたのシナリオはgroupingBy
コレクターのために良いユースケースのように聞こえます。通常、等価関数を提供する代わりに、修飾子を抽出する関数を指定します。要素はリスト内のこれらの修飾子にマップされます。場合
すなわち
Map<Qualifier, List<T>> map = list.stream()
.collect(Collectors.groupingBy(T::getQualifier));
Collection<List<T>> result = map.values();
T
のアイデンティティは、あなたが引数としてFunction.identity()
使用することができ、あなたの修飾子です。
これは、修飾子がT
の1つ以上のフィールドである場合に問題になります。タプル型を使用して、T
の代替IDを作成することもできますが、フィールドの数ごとに別々のタプルクラスが必要になるため、これまでのところしかありません。
あなたがgroupingBy
あなたを使用したい場合は、本当にT
ための温帯別のIDを作成する必要があるので、あなたはT
のequals
とhashCode
方法を変更する必要はありません。
適切なIDを作成するには、equals
とhashCode
を実装する必要があります(または、パフォーマンスが低下するハッシュコードの場合は常に0
を返します)。そこ私の知っている、このためのAPIクラスは、ありませんが、私は単純な実装作られています
interface AlternateIdentity<T> {
public static <T> Function<T, AlternateIdentity<T>> mapper(
BiPredicate<? super T, Object> equality, ToIntFunction<? super T> hasher) {
return t -> new AlternateIdentity<T>() {
@Override
public boolean equals(Object other) {
return equality.test(t, other);
}
@Override
public int hashCode() {
return hasher.applyAsInt(t);
}
};
}
}
あなたのような使用できます。
Collection<List<T>> result
= list.stream()
.collect(Collectors.groupingBy(
AlternateIdentity.mapper(eqF, hashF)
))
.values();
eqF
は、あなたの関数をある
、そしてhashF
があるがeqF
と同じフィールドをハッシュするハッシュコード関数。また0
をhashF
に返すこともできますが、適切な実装をすると処理が速くなります)
要素をグループ化するカスタム関数が真偽を返す場合、3つ以上のグループを持つことはできますか? – Tunaki
@ Tunaki - これは等価クラスへの分割と呼ばれています。オブジェクトが整数であり、等価(真/偽)が3を法として計算される(すなわち、それらが同じ残余を有する場合、それらは等しい)と仮定する。バイナリの等価性テストであっても、1から100までの整数は3つのバケットになります。 –
など。 * F *要素があり、他の要素と等しくはありません。それは1つの要素のグループを作ります。 –