Java 12の新機能:The Teeing Collector

この記事では、Java 12で導入された新しいコレクターについて説明します。この新しい機能は、「 コレクターの作成 」という見出しのマイナーな変更要求であったため、公式JEPでは発表されませんでした。 2つのコレクターからの結果を結合するように設計されています。





すべて興味深い-カットの下で





それでもコレクターが何かわからない場合
コレクターは、ストリームを別のデータ構造に変換するために使用される特別なクラスです。 たとえば、 list



 list = Stream.of(1,2,3).collect(Collectors.toList()); //     1, 2  3
      
      





これは、新しいストリームを作成し、すぐに変換するため、役に立たない例です。 コレクターの使用を示すために発明されました。



ドキュメント



ここをクリックしてCollectors#teeing



を表示します 。 公式文書によると:

「...は、2つの従属コレクターで構成されるコレクターを返します。 結果のコレクターに転送された各要素は、両方の従属コレクターによって処理され、それらの結果は、最終結果に接続する特別な関数を使用して結合されます。

オリジナル
「...は2つのダウンストリームコレクタの複合であるコレクタを返します。結果のコレクタに渡されるすべての要素は両方のダウンストリームコレクタによって処理され、指定されたマージ関数を使用して結果が最終結果にマージされます。」

メソッドヘッダー:



 static <T, R1, R2, R> Collector<T, ?, R> teeing( Collector<? super T, ?, R1> downstream1, Collector<? super T, ?, R2> downstream2, BiFunction<? super R1, ? super R2, R> merger)
      
      





興味深い事実



これはティーです (英語からティー):







Teeing



Teeing



から来ました。 ウィキペディアによると、「T字は、液体の流れ(この場合、ストリーム、ストリーム-ストリーム/ストリーム、コメントトランスレータ)を結合(または分割)するために使用される最も一般的な継手(パイプラインの接続部分、およそ翻訳者)です。」

他の名前が提案されました:二分(2_partsに分割)、二重化、分岐(分割)、レプリケーター、ファンアウト(分割)、タッピング、解凍、collectionToBothAndThen、biCollecting、展開(拡張)、分岐など

コア開発者によって評価されたすべての選択肢は、 ここにあります

使用例



異なる難易度でコードを使用する3つの例をコンパイルしました。



ゲストリスト



ストリーム内のオブジェクトのリストから2種類の情報を抽出します。 各ゲストは招待を受け入れなければならず、家族を導くことができます。 誰が予約を確認した か、参加者総数 (ゲストと家族を含む)を知りたい。



 var result = Stream.of( // Guest(String name, boolean participating, Integer participantsNumber) new Guest("Marco", true, 3), new Guest("David", false, 2), new Guest("Roger",true, 6)) .collect(Collectors.teeing( //  ,    ,    Collectors.filtering(Guest::isParticipating, //        Collectors.mapping(o -> o.name, Collectors.toList())), //  ,       Collectors.summingInt(Guest::getParticipantsNumber), //      , //    EventParticipation::new )); System.out.println(result); //  // EventParticipation { guests = [Marco, Roger], // total number of participants = 11 }
      
      







ゲスト
 class Guest { private String name; private boolean participating; private Integer participantsNumber; public Guest(String name, boolean participating, Integer participantsNumber) { this.name = name; this.participating = participating; this.participantsNumber = participantsNumber; } public boolean isParticipating() { return participating; } public Integer getParticipantsNumber() { return participantsNumber; } }
      
      







イベント参加
 class EventParticipation { private List<String> guestNameList; private Integer totalNumberOfParticipants; public EventParticipation(List<String> guestNameList, Integer totalNumberOfParticipants) { this.guestNameList = guestNameList; this.totalNumberOfParticipants = totalNumberOfParticipants; } @Override public String toString() { return "EventParticipation { " + "guests = " + guestNameList + ", total number of participants = " + totalNumberOfParticipants + " }"; }}
      
      







2つの異なるリストのフィルター名



この例では、フィルターに従って名前のストリームを2つのリストに分割します。



 var result = Stream.of("Devoxx", "Voxxed Days", "Code One", "Basel One", "Angular Connect") .collect(Collectors.teeing( //   Collectors.filtering(n -> n.contains("xx"), Collectors.toList()), //   Collectors.filtering(n -> n.endsWith("One"), Collectors.toList()), //  -       (List<String> list1, List<String> list2) -> List.of(list1, list2) )); System.out.println(result); // -> [[Devoxx, Voxxed Days], [Code One, Basel One]]
      
      





数のストリームをカウントして追加する



合計とカウントを組み合わせて平均値を取得するブログに、同様の例が表示されるのを見たことがあるかもしれません。 この例ではAverageInt



あり、 AverageInt



と単純なコレクターを使用するだけです。



次の例では、 Teeing



関数を使用して2つの値を返します。



 var result = Stream.of(5, 12, 19, 21) .collect(Collectors.teeing( //   Collectors.counting(), //   Collectors.summingInt(n -> Integer.valueOf(n.toString())), // : (count, sum) -> new Result(count, sum); Result::new )); System.out.println(result); // -> {count=4, sum=57}
      
      





結果
 class Result { private Long count; private Integer sum; public Result(Long count, Integer sum) { this.count = count; this.sum = sum; } @Override public String toString() { return "{" + "count=" + count + ", sum=" + sum + '}'; }}
      
      







可能性のあるトラップ



Map.Entry


多くの例では、 Map.Entry



を使用してBiFunction



結果を保存しMap.Entry



Map



最後の引数を保存できないため、これを行わないでください。 Java Coreには、2つの値を格納するための標準オブジェクトはありません-自分で作成する必要があります。



Java 12の新機能について



このプレゼンテーションでは、Java 12に関するより多くの情報と興味深い事実を見つけることができます。



成功したグッズ!



All Articles