Stream.forEach()
を使用している場合、ストリームが空でないときに実行される事前アクションと事後アクションを追加できないと考えていました。たとえば、Listを印刷するときに、ストリームが空のときに何かを前置きするか、何かを書くことができます。 Javaストリーム - 事前アクションとポストアクションのある
private static <T> void forEach(Stream<T> stream, Consumer<? super T> action,
Runnable preAction, Runnable postAction, Runnable ifEmpty) {
AtomicBoolean hasElements = new AtomicBoolean(false);
Consumer<T> preActionConsumer = x -> {
if (hasElements.compareAndSet(false, true)) {
preAction.run();
}
};
stream.forEach(preActionConsumer.andThen(action));
if (hasElements.get()) {
postAction.run();
} else {
ifEmpty.run();
}
}
ような何かを思い付いた、これはいけない、動作するはず? この方法は正しいですか?それは「良いアイデア」がそのような方法を持っているのか、それとも何か警告がありますか?は、action
を実行している別のスレッドよりも遅いかもしれませんが、並列ストリームの目的を無効にする同期またはその他の並行性ユーティリティに頼らずに正しく実装するため、並列ストリームでは機能しません。 ..
編集:追加ユースケース。正規表現を使用してファイルから整数を検索し、別のファイルに書き出します。このアプローチを使用すると、メモリ内に文字列を作成する必要はなく、その後にファイルに書き込むことができます。 (もちろん、私の本当の仕事のために、私はより複雑な正規表現を使用しています。)
public static void main(String[] args) throws IOException {
Stream<String> lines = Files.lines(Paths.get("foo.txt"));
Pattern findInts = Pattern.compile("(\\d+)");
Path barFile = Paths.get("bar.txt");
try (BufferedWriter writer = Files.newBufferedWriter(barFile , StandardOpenOption.CREATE_NEW)) {
lines.flatMap(x -> findInts.matcher(x).results())
.forEach(x-> convertCheckedIOException(() -> {
writer.write(x.group(1));
writer.newLine();
})
);
}
}
public static void convertCheckedIOException(Run r) {
try {
r.run();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
interface Run {
void run() throws IOException;
}
Streamが_not_空であれば 'isEmpty'は' true'です... –
真実ですが、変数名は質問の要点ではないので、私はそれを変更すると思います – user140547
私はちょっと試してみました...もしかしたら、プレアクションがとにかく終了するまでアクションを止めたいのであれば、ポストアクションのようにストリームの外で実行する方が簡単でしょうか? preActionConsumerは、要素があるかどうかをチェックするために使用されます(また、ブール値へのアクセスを毎回禁止するためにデリゲートを切り替えることもできます)。 –