Edited at

[Java] StreamのCollectorsのメモ


個人的なメモ


  • 忘れてしまうので、よく使いそうなパターンを記載

  • 本当によく使うパターンは、自家版 Collectorsクラス/メソッドを作ってもいいのかも


Collectors#toMap()


LinkedHashMapを使いたい

明示的に LikedHashMap を使いたい。

ついでに、キー重複を許したい。

    public static <T, K, V> Collector<T, ?, Map<K, V>> toMap(

Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {

return Collectors.toMap(
keyMapper,
valueMapper,
(a, b) -> b,
LinkedHashMap::new);
}

キー重複を許したくない場合には、例外を投げる。

(a, b) -> { throw new IllegalStateException(~); }

詳細は、標準の2引数 Collectors#toMap() を参照。


TreeMap を使いたい

キーで自然にソートしたい。

ほぼ同じ。

    public static <T, K, V> Collector<T, ?, Map<K, V>> toTreeMap(

Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {

return Collectors.toMap(
keyMapper,
valueMapper,
(a, b) -> b,
TreeMap::new); // ★ここ
}

TreeMapにComparator を指定したいときは、コンストラクタ参照ではなくラムダ式で指定。


Collectors#toSet()


LinkedHashSetを使いたい

ここは toSet() ではなく、toCollection() を使うのがポイント。

    public static <T> Collector<T, ?, Set<T>> toSet() {

return Collectors.toCollection(LinkedHashSet::new);
}


TreeSetを使いたい

基本同じ。

    public static <T> Collector<T, ?, Set<T>> toTreeSet() {

return Collectors.toCollection(TreeSet::new);
}


Collectors#groupingBy


LinkedHashMapを使いたい

    public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(

Function<? super T, ? extends K> classifier) {

return Collectors.groupingBy(classifier,
LinkedHashMap::new, // ★ここ
Collectors.toList());
}


TreeMapを使いたい

同じ。

    public static <T, K> Collector<T, ?, Map<K, List<T>>> orderedGroupBy(

Function<? super T, ? extends K> classifier) {

return Collectors.groupingBy(classifier,
TreeMap::new, // ★ここ
Collectors.toList());
}


要素をListじゃなくSetにしたい

…良いメソッド名が思いつかない。

    public static <T, K> Collector<T, ?, Map<K, Set<T>>> groupingBySet(

Function<? super T, ? extends K> classifier) {

return Collectors.groupingBy(classifier,
TreeMap::new,
Collectors.toCollection(LinkedHashSet::new)); // ★ここ
}

もちろん目的に応じて、TreeSetや、普通の Collectors.toSet() でもOK。


グルーピング時にListに詰める要素も変換したい

    public static <T, K, D> Collector<T, ?, Map<K, List<D>>> groupingBy(

Function<? super T, ? extends K> classifier,
Function<? super T, ? extends D> mapper) {

return Collectors.groupingBy(classifier,
LinkedHashMap::new,
Collectors.mapping(mapper, // ★ここ
Collectors.toList()));
}

もちろん、List じゃなくて Set でもOK。


Collectors#collectingAndThen

変更不可な Map や List を生成したい場合。

    public static <T, K, V> Collector<T, ?, Map<K, V>> toConstMap(

Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {

return Collectors.collectingAndThen(
Collectors.toMap(
keyMapper,
valueMapper),
Collections::unmodifiableMap);
}