web-dev-qa-db-ja.com

コレクター(Java)でのgroupingbyとマッピングの違いは何ですか?

このコードを見てください。

// group by price, uses 'mapping' to convert List<Item> to Set<String>
    Map<BigDecimal, Set<String>> result =
            items.stream().collect(
                    Collectors.groupingBy(Item::getPrice,
                            Collectors.mapping(Item::getName, Collectors.toSet())
                    )
            );

GroupingByとMappingは交換可能ですか?それらの違いは何ですか?

Collect()の3番目のパラメーターで、Collectors.toSet()の代わりにCollectors.toList()を使用した場合、同じ出力タイプMapを取得できますか? toList()がより人気のあるオプションだと聞きました。

15
NoMoreErrors

GroupingByとMappingは交換可能ですか?

いいえ、まったく異なります。 groupingByを使用すると、Mapを作成できます。ここで、キーはgroupingByに渡される最初の引数であり、値はListの要素タイプのStreamです。

Collectors.groupingBy(Item::getPrice)は_Map<BigDecimal, List<Item>>_を生成します(_Item::getPrice_がBigDecimalを返すと仮定します。mappingCollectorCollectors.groupingBy()に引数として渡すと、出力の値を変更できますマップ(あなたの例では、それを_Set<String>_に変更します)。

Collect()の3番目のパラメーターで、Collectors.toSet()の代わりにCollectors.toList()を使用した場合、同じ出力タイプMapを取得できますか?

いいえ、_Map<BigDecimal, List<String>>_を取得します。

17
Eran

いいえ、2つは完全に異なります。

_Collectors.groupingBy_は、キーを作成し、キーから同じキーを持つストリーム内のオブジェクトのコレクションへのマップを返すコレクターを返す関数を取ります。

一方、_Collectors.mapping_は、関数と別のコレクターを受け取り、新しいコレクターを作成します。このコレクターは、最初に関数を適用し、次に指定されたコレクターを使用してマップされた要素を収集します。したがって、以下は同等です。

_items.stream().map(f).collect(c);
items.stream().collect(Collectors.mapping(f, c));
_

_Collectors.mapping_は、ストリームがなくてもコレクターを直接渡す必要がある場合に最も役立ちます。そのような状況の例は、_Collectors.groupingBy_を使用する場合です。

_items.stream().collect(Collectors.groupingBy(Item::getPrice, Collectors.toSet()))
_

_Map<BigDecimal,Set<Item>>_を生成します(getPrice()BigDecimalを返すと仮定)。しかしながら、

_items.stream().collect(Collectors.groupingBy(Item::getPrice,
    Collectors.mapping(Item::getName, Collectors.toSet())))
_

_Map<BigDecimal,Set<String>>_を返します。アイテムを収集する前に、まず_Item.getName_を適用します。

15
Hoopje