グループ化する任意の数の属性を持つ関数を作成して、groupingBy
- Collector
をループ内に作成し、毎回自分自身の前のバージョンをdownstream
コレクタとして渡すことができます。
public static <T> Map collectMany(List<T> data, Function<T, ?>... groupers) {
Iterator<Function<T, ?>> iter = Arrays.asList(groupers).iterator();
Collector collector = Collectors.groupingBy(iter.next());
while (iter.hasNext()) {
collector = Collectors.groupingBy(iter.next(), collector);
}
return (Map) data.stream().collect(collector);
}
あなたは逆の順序で渡す(または関数内にそれらを逆に、例えば、あなたが好む方、Collections.reverse
を用いて、またはグアバのLists.reverse
)しなければならないので、grouper
機能の順序が逆であることに留意されたいです。
Object groupedData = collectMany(data, Person::getTown, Person::getCountry, Person::getName);
またはこのような、機能の配列を逆にする古い学校for
ループを使用して、あなたは逆の順序でハタを渡す必要はありません(ただし、IMHO、これは理解しにくい)例:
public static <T> Map collectMany(List<T> data, Function<T, ?>... groupers) {
Collector collector = Collectors.groupingBy(groupers[groupers.length-1]);
for (int i = groupers.length - 2; i >= 0; i--) {
collector = Collectors.groupingBy(groupers[i], collector);
}
return (Map) data.stream().collect(collector);
}
どちらの方法も元のコードと同じようにMap<?,Map<?,Map<?,T>>>
を返します。そのデータで何をしたいのかに応じて、TunakiのようにMap<List<?>,T>
を使用することを検討する価値があります。
「時々、名前と町によって、時には属性によってグループ化したいと思っています。 - ユーザーの入力や何に応じて? – Smutje
も参照してくださいhttp://stackoverflow.com/a/34772639/1587046 –