JavaにStream
チェーンを壊さずにStream
のすべての要素に関数を適用する方法はありますか? forEach
を呼び出すことができますが、そのメソッドはvoid
ではなくStream
を返します。
(少なくとも)3つの方法があります。サンプルコードのために、2つのコンシューマメソッドmethodA
およびmethodB
を呼び出すと仮定しました。
A. peek()
を使用します。
list.stream().peek(x -> methodA(x)).forEach(x -> methodB(x));
ドキュメントは「デバッグ」のためにのみ使用すると述べていますが、動作します(そして、現在生産中です)
B. map()
を使用してmethodAを呼び出し、要素をストリームに戻します。
list.stream().map(x -> {method1(x); return x;}).forEach(x -> methodB(x));
これはおそらく最も「受け入れられる」アプローチです。
C. forEach()
で2つのことを行います。
list.stream().forEach(x -> {method1(x); methodB(x);});
これは柔軟性が最も低く、ニーズに合わない場合があります。
Stream
のmap()
関数を探しています。
例:
List<String> strings = stream
.map(Object::toString)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
最適なオプションは、ストリームにマップを適用することです。これは、たとえば次のように、このストリームの要素に指定された関数を適用した結果で構成されるストリームを返します。
IntStream.rangeClosed(40, 70).limit(20).mapToObj(i -> (Integer) i).map(item->item+3).map(item->item*2)...
(StreamItemABCタイプのアイテムのストリーム)
ストリームにいくつかの変更を適用していますが、この方法では、引数をmapメソッドに渡して修正することはできません。
private void applyMethod(ParameterX parX) {
someStreamX().map(n -> methodX(n, parX))...
}
private StreamItemABC methodX (StreamItemABC item, ParameterX parX) {
return notification;
}
breaking the stream chain
の意味が完全にはわかりませんが、Stream
を返すStream
の操作は、ストリームをbreakまたはconsumeしません。ストリームはterminal operations
によって消費され、forEach
返さない a Stream<T>
に注意して、forEachおよびforEachの前にすべてのintermediate
操作を実行することにより、ストリームを終了します。自体。
コメントで提供した例では:
myStream.map(obj -> {obj.foo(); return obj;}
ライナー1つでこれを行うことはできません。もちろん、メソッド参照を使用することもできますが、返されるStream
は異なる型になります(foo
が型を返すと仮定します):
myStream.map(Obj::foo) // this will turn into Stream<T>, where T is
// the return type of foo, instead of Stream<Obj>
それに加えて、map
操作はstateful
であるため、強くお勧めしません。コードはコンパイルされ、希望どおりに機能する場合もありますが、後で失敗する可能性があります。 map
操作はstateless
でなければなりません。
Stream.peek
を探していると思います。ただし、主にデバッグ方法として設計されているため、ドキュメントを注意深く読んでください。ドキュメントから:
このメソッドは、主にデバッグをサポートするために存在します。ここでは、パイプラインの特定のポイントを通過する要素を表示します。
peek
に渡されるアクションは、 non-interfering でなければなりません。
最もクリーンな方法は、ストリーム内のオブジェクトにミューテーターを追加することだと思います。
例えば、
class Victim {
private String tag;
private Victim withTag(String t)
this.tag = t;
return this;
}
}
List<Victim> base = List.of(new Victim());
Stream<Victim> transformed = base.stream().map(v -> v.withTag("myTag"));
必要に応じて(多くの場合)、withTagメソッドで新しいVictimを作成して返すことができます。これにより、Victimを不変にすることができます。