你的情況聽起來是個不錯的用例爲groupingBy
收集器。通常,不提供相等函數,而是提供一個提取限定符的函數。元素然後映射到列表中的這些限定符。
即
Map<Qualifier, List<T>> map = list.stream()
.collect(Collectors.groupingBy(T::getQualifier));
Collection<List<T>> result = map.values();
在案件的T
的身份是你的預選賽中,你可以使用Function.identity()
作爲參數。
但是當您的限定符超過1個字段T
時,這會成爲問題。您可以使用元組類型來爲T
創建一個替代標識,但是這僅僅到目前爲止,因爲每個字段數都需要單獨的元組類。
如果你想使用groupingBy
你真的需要爲T
創建溫帶替補身份,所以你不必改變T
的equals
和hashCode
方法。
要創建一個合適的身份,您需要實現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
測試相同的字段。 (同樣,你也可以在hashF
中返回0
,但是正確的實現會加快速度。)
如果用於分組元素的自定義函數返回一個布爾值,那麼如何擁有兩個以上的組? – Tunaki
@Tunaki - 這就是所謂的劃分爲等價類。假設對象是整數並且等式(真/假)以模3計算(即,如果它們具有相同的餘數則它們相等)。然後,從1到100的整數將以三個桶結束,即使它是一個二進制相等性測試。 –
例如有* F *元素,它不等於任何其他元素。它使一組元素。 –