stream を途中で分岐させたいです
例えば、得点が60点以上だった場合に1ポイント、80点以上だった場合に2ポイント、90点以上は 3 + (n - 90) ポイント付与する条件で、ポイントの合計が欲しい場合。
streamを分岐できれば簡単に書けると思うのですが、やりようはないでしょうか
コードのイメージとしてはこんなかんじです
Java
1Stream<Integer> stream = Stream.of(1, 2, 3, 60, 65, 85, 90, 92, 95); 2Integer sum = stream.flatMap( 3 fork( 4 branch(n -> n < 60).map(n -> 0), 5 branch(n -> n < 80).map(n -> 1), 6 branch(n -> n < 90).map(n -> 2), 7 branch().map(n -> 3 + (90 - n)) 8 ) 9 ) 10 .mapToInt(Integer::valueOf) 11 .sum();
ちなみに、途中で終端処理を挟まない方法を模索中です
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
実現したいのは、下記のようなデーターフローでしょうか?
[Source] --> [FilterX] --> [Split] --> [FilterA] --> [SinkA] +------> [FilterB] --> [SinkB]
残念ながら、Java8のストリーム(java.util.stream.Stream
)は、汎用のデータフロー・パイプライン処理のための仕組みではありません。出力先が2個以上あるような「分岐」は表現不可能です。
1つのストリームは、必ず「1つのソース」+「0個以上の中間操作」+「1つの終端操作」から構成されます。
Streamが何を目的としたものであるかや、その内部的な動作については 社内Java8勉強会 ラムダ式とストリームAPI が参考になるかと思います。
投稿2015/07/31 14:28
総合スコア6191
0
グルーピング化して、それぞれ計算するようにしてみるぐらいしか方法はないかなと思います。
並列化もしているので、時間がかかる処理もマルチスレッドでよしなにやってくれるはずです。
こんな感じでいかがでしょうか?
(もうちょっとうまいか書き方はあるかもしれません)
Java
1import java.util.stream.*; 2 3public class SumPoint2 { 4 public static void main(String[] args) { 5 Stream<Integer> stream = Stream.of(1, 2, 3, 60, 65, 85, 90, 92, 95); 6 Integer sum = stream.collect(Collectors.groupingByConcurrent((n) -> { 7 if (n >= 90) { 8 return "A"; 9 } else if (n >= 80) { 10 return "B"; 11 } else if (n >= 60) { 12 return "C"; 13 } else { 14 return "Z"; 15 } 16 })).entrySet().parallelStream().mapToInt((e) -> { 17 switch(e.getKey()) { 18 case "A": 19 return e.getValue().stream().mapToInt(n -> 3 + (n - 90)).sum(); 20 case "B": 21 return 2 * e.getValue().size(); 22 case "C": 23 return e.getValue().size(); 24 } 25 return 0; 26 }).sum(); 27 28 System.out.println(sum); // => 20 29 } 30}
以下は普通にする、修正前の回答です。
Streamを使うのであれば、処理を分岐させるのではなく、
各ポイントにマッピングすると考えた方がいいです。
下のような感じはいかがでしょうか?
Java
1import java.util.stream.*; 2 3public class SumPoint { 4 public static void main(String[] args) { 5 IntStream stream = IntStream.of(1, 2, 3, 60, 65, 85, 90, 92, 95); 6 Integer sum = stream 7 .map((n) -> { 8 if (n >= 90) { 9 return 3 + (n - 90); 10 } else if (n >= 80) { 11 return 2; 12 } else if (n >= 60) { 13 return 1; 14 } else { 15 return 0; 16 } 17 }) 18 .sum(); 19 System.out.println(sum); // => 20 20 } 21}
投稿2015/07/30 22:06
編集2015/07/31 10:22総合スコア21735
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/07/31 10:23
2015/07/31 15:40
2015/07/31 21:03
0
集合の中の部分集合毎単位で処理を記述したい
ということであれば元のストリームから目的の要素を(filterで)抜き出したストリームを作ればいいのでは?
java
1IntStream grade0 = stream.filter((n) -> EvaluationRule.classify(n) == 0);
合計などが欲しくなったら分けたストリームを統合すればいいでしょう。
思いっきりC#のノリで書いてしまいましたが、
javaのStreamは使い回しができないので
一々ストリーム元からストリームを生成する必要がありました。
java
1int[] source = { 1,2,3,4,5}; 2IntStream s1 = Arrays.stream(source).filter(i -> i < 3).map(i -> 1); 3IntStream s2 = Arrays.stream(source).filter(i -> i >= 3).map(i -> 2); 4IntStream s12 = IntStream.concat(s1, s2);
投稿2015/07/31 00:31
編集2015/07/31 01:49総合スコア13521
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/07/31 01:15 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/07/31 15:29