Collectorsクラスの静的ファクトリメソッド
ファクトリメソッド | 戻り値の型 | 効果 |
---|---|---|
toList | List<T> |
ストリーム内のすべてのアイテムをリストに収集します |
toSet | Set<T> |
ストリーム内のすべてのアイテムをセットに収集し、重複を削除します |
toCollection | Collection<T> |
ストリーム内のすべてのアイテムを、特定の供給元によって作成されたコレクションに収集しますmenuStream.collect(toCollection(), ArrayList::new) |
カウント | 長いです | ストリーム内の要素の数を数える |
sumInt | 整数 | ストリーム内のアイテムの整数属性を合計します |
平均化Int | ダブル | ストリーム内のアイテムのIntegerプロパティの平均値を計算します |
summarizingInt | IntSummaryStatistics | 最大、最小、合計、平均など、ストリーム内のアイテムの整数プロパティに関する統計を収集します |
接合 | ストリング | ストリーム内の各アイテムに対してtoStringメソッドを呼び出して生成された文字列を接続しますcollect(joining(", ")) |
maxBy | Optional<T> |
指定されたコンパレータによって選択された最大の要素をストリーム内でラップするオプション、またはストリームが空の場合はOptional.empty() |
私の町 | Optional<T> |
指定されたコンパレータによって選択された最小の要素をストリーム内でラップするオプション、またはストリームが空の場合はOptional.empty() |
削減 | 削減操作によって生成されたタイプ | アキュムレータとしての初期値から始めて、BinaryOperatorを使用してストリーム内の要素を1つずつ結合し、それによってストリームを単一の値に減らします。累加int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum)); |
収集し、その後 | 変換関数によって返されるタイプ | 別のコレクターをラップし、その結果に変換関数を適用しますint howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size)) |
groupingBy | Map<K, List<T>> |
アイテムの属性の値に従ってストリーム内のアイテムをグループ化し、属性値を結果マップのキーとして使用します |
partitioningBy | Map<Boolean,List<T>> |
ストリーム内の各アイテムに述語を適用した結果に基づいてアイテムを分割します |
コレクター
Collectorsクラスにはすべて事前定義された実装があります。一般的な一般的な方法は、読みやすさを向上させるために次の静的インポートを使用することです。
import static java.util.stream.Collectors.*;
または、選択したコレクターを個別にインポートします。
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
以下のすべての例では、次のデモデータ収集を使用します
List<String> givenList = Arrays.asList("a", "bb", "ccc", "dd");
Collectors.toList()
ToListメソッドは、リストインスタンスへのストリーム内のすべての要素を収集できます。このメソッドを使用しても、Listの特定の実装を想定できないことに注意してください。Listの実装を指定する場合は、代わりにtoCollectionを使用する必要があります。次の例では、要素のシーケンスを表すストリームインスタンスを作成し、それを収集します。 Listインスタンスオブジェクトに。
List<String> result = givenList.stream().collect(toList());
Collectors.toSet()
ToSetメソッドは、Setインスタンスへのストリーム内のすべての要素を収集できます。このメソッドを使用しても、Setの特定の実装を想定できないことに注意してください。Set実装を指定する場合は、代わりにtoCollectionを使用する必要があります。例では、要素のシーケンスを表すストリームインスタンスを作成し、それをSetインスタンスオブジェクトに収集します
Set<String> result = givenList.stream().collect(toSet());
セットには繰り返し要素が含まれていません。セットに重複する要素がある場合、セットには1つだけが保持されます。
List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
Set<String> result = listWithDuplicates.stream().collect(toSet());
assertThat(result).hasSize(4);
Collectors.toCollection()
toSetおよびtoListコレクターでは、その実装を指定できないことに気付いたかもしれません。特定の実装を使用する場合は、toCollectionコレクターを使用して、特定のコレクション実装を提供する必要があります。次の例では、要素のシーケンスを表すストリームインスタンスを作成し、それをLinkedListインスタンスオブジェクトに収集します。
List<String> result = givenList.stream().collect(toCollection(LinkedList::new))
ここでは不変のコレクションを使用できないことに注意してください。カスタムコレクターを介して実現するか、collectingAndThenを使用します。
Collectors.toMap()
ToMapコレクターは、ストリーム要素をMapインスタンスに収集するために使用されます。この関数を実装するには、次の2つの関数が必要です。
- keyMapper
- valueMapper
keyMapperは、ストリーム要素からマップのキーを抽出するために使用され、valueMapperは、関連付けることができる値を抽出します。
次の例では、ストリーム要素をマップに収集し、文字列をキーとして、その長さを値として格納します。
Map<String, Integer> result = givenList.stream()
.collect(toMap(Function.identity(), String::length))
Function.identity()は、受信したパラメーターを返す事前定義されたショートカット関数です。
コレクションに重複する要素がある場合はどうなりますか?toSetとは異なり、toMapは繰り返される要素をフィルタリングできません。これは理解しやすいです-キーが関連付けられている値を決定する方法は?
List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
assertThatThrownBy(() -> {
listWithDuplicates.stream().collect(toMap(Function.identity(), String::length));
}).isInstanceOf(IllegalStateException.class);
toMapは値が等しいかどうかさえ判断せず、キーが繰り返されると、IllegalStateExceptionがすぐにスローされることがわかります。キーが競合する場合は、toMapの別のオーバーロードされたメソッドを使用する必要があります。
Map<String, Integer> result = givenList.stream()
.collect(toMap(Function.identity(), String::length, (item, identicalItem) -> item));
3番目のパラメーターは二項演算であり、キーの競合を処理する方法を指定できます。この例では、2つの長さが常に同じであるため、任意の1つを選択できます。
Collectors.collectingAndThen()
CollectingAndThenは、収集が完了した後に結果に対して他のアクションを実行できる特別なコレクターです。以下は、ストリーム要素をListの例に収集し、その結果をImmutableListの例に変換します。
List<String> result = givenList.stream()
.collect(collectingAndThen(toList(), ImmutableList::copyOf))
Collectors.joining()
結合コレクターを使用して、文字列ストリーム内の要素を結合できます。例は次のとおりです。
String result = givenList.stream()
.collect(joining());
結果は次のとおりです。
"abbcccdd"
区切り文字、接頭辞、接尾辞を指定することもできます。
String result = givenList.stream()
.collect(joining(" "));
結果は次のとおりです。
"a bb ccc dd"
別の例を見てください:
String result = givenList.stream()
.collect(joining(" ", "PRE-", "-POST"));
結果は次のとおりです。
"PRE-a bb ccc dd-POST"
Collectors.counting()
カウントは、要素の数を返す単純なコレクターです。
Long result = givenList.stream()
.collect(counting());
Collectors.summarizingDouble / Long / Int()
SummarizingDouble / Long / Intコレクターは、ストリームで抽出された数値要素の統計結果タイプを返します。次の例では、文字列の長さの情報を取得します。
DoubleSummaryStatistics result = givenList.stream()
.collect(summarizingDouble(String::length));
次のテストコードが実行されます。
assertThat(result.getAverage()).isEqualTo(2);
assertThat(result.getCount()).isEqualTo(4);
assertThat(result.getMax()).isEqualTo(3);
assertThat(result.getMin()).isEqualTo(1);
assertThat(result.getSum()).isEqualTo(8);
Collectors.averagingDouble / Long / Int()
AveragingDouble / Long / Intは、返されたストリームで抽出された要素の平均値です。次の例では、平均文字列長を計算します。
Double result = givenList.stream()
.collect(averagingDouble(String::length));
Collectors.summingDouble / Long / Int()
SummingDouble / Long / Intは、抽出された要素の合計を返します。次に、すべての文字列の長さの合計を計算します。
Double result = givenList.stream()
.collect(summingDouble(String::length));
Collectors.maxBy()/ minBy()
MaxBy / MinByコレクターは、提供されたComparatorインスタンスに従って、ストリーム内の最大要素と最小要素を返します。最大要素は次のように計算されます。
Optional<String> result = givenList.stream()
.collect(maxBy(Comparator.naturalOrder()));
結果はオプションタイプであり、ユーザーは空のコレクションを考慮する必要があることに注意してください。
Collectors.groupingBy()
グループ化コレクターは、属性に従って要素をグループ化し、それらをMapインスタンスに格納するために使用されます。次の例では、文字列の長さに従ってグループ化し、結果をセットに格納します。
Map<Integer, Set<String>> result = givenList.stream()
.collect(groupingBy(String::length, toSet()));
テストコードは次のとおりです。
assertThat(result)
.containsEntry(1, newHashSet("a"))
.containsEntry(2, newHashSet("bb", "dd"))
.containsEntry(3, newHashSet("ccc"));
2番目のパラメーターはコレクションです。任意のコレクション実装を使用できます。
Collectors.partitioningBy()
PartitioningByは、述語インスタンスに従ってフロー要素をマップに収集し、ブール値をキーとして、値をセットとして格納する特別なグループ化コレクターです。「true」キーは一致した要素のセットに対応し、「false」キーは一致しなかった要素のセットです。サンプルコードは次のとおりです。
Map<Boolean, List<String>> result = givenList.stream()
.collect(partitioningBy(s -> s.length() > 2))
結果のマップは次のとおりです。
{false=["a", "bb", "dd"], true=["ccc"]}
Collectors.teeing()
これまでに学んだことに従って、最大値と最小値を見つけます。
List<Integer> numbers = Arrays.asList(42, 4, 2, 24);
Optional<Integer> min = numbers.stream().collect(minBy(Integer::compareTo));
Optional<Integer> max = numbers.stream().collect(maxBy(Integer::compareTo));
// do something useful with min and max
ここでは、2つの未使用のコレクターを使用し、コレクションをマージして対応するビジネスを実装します。Java 12より前は、このような機能を実現するために、ストリームに対して2つの操作を実行し、中間結果を一時オブジェクトに格納し、最後にマージして返す必要がありました。
幸い、Java 12には、これらの手順を処理するのに役立つ組み込みのコレクターが用意されています。必要なのは、2つのコレクターとマージ関数だけです。
新しいコレクターティーは、フロー上で2つの異なる方向に操作を実行するため、Tコレクターと呼ばれます。
numbers.stream().collect(teeing(
minBy(Integer::compareTo), // The first collector
maxBy(Integer::compareTo), // The second collector
(min, max) -> // Receives the result from those collectors and combines them
));