JavaのStreamインターフェースについて。
|
||
JDK1.8で導入されたStreamは、複数の値(オブジェクト)に対して何らかの処理(変換や集計)を行う事を分かりやすく記述できる。
import java.util.stream.Stream;
Streamの値の持ち方はjava.util.Listのようなイメージ。
しかしStreamの操作は一度しか行えないので(ScalaのTraversableOnce相当)、java.util.Iteratorの方が近いかも。
つまり複数の値を保持し、順次処理していく。
Streamには色々な処理を行うメソッドが用意されている。
一部のメソッド(forEach)はコレクションクラス(List・Queue・Set(Iterable))に直接用意されているが、基本的には、コレクションや配列からStreamを生成して使用する。
Streamで行った操作結果をコレクションにしたい場合は、collectメソッドを使ってコレクションに変換する。
ちなみにScalaの場合は、コレクションはJavaのStreamのようなメソッドをまとめたインターフェースを実装している(Scalaなので、厳密にはトレイトをミックスインしている)ので、
List(Seq)や配列(Array)のままで(Streamへの変換のような事をせずに)JavaのStreamのような記述を行うことが出来る。
なお、java.util.stream.Streamと同様な位置付け(無限データを扱える)のscala.collection.immutable.Streamというクラスもある。
Streamを使うと、以下のように処理が簡単に(宣言的に)書ける。
例 | Streamを使用 | Streamを使わずに記述 | Scala相当 |
---|---|---|---|
String→Pathの変換 |
List<String> slist = Arrays.asList("a.txt", "b.txt"); |
List<String> slist = Arrays.asList("a.txt",
"b.txt"); |
val slist = Seq("a.txt", "b.txt") |
Path→Stringの変換 |
List<String> slist2 = plist.stream() |
List<String> slist2 = new ArrayList<>(); |
val slist2 = plist.map(_.toString) |
Stringのメソッド名一覧取得 (重複排除つき) |
List<String> mlist = Arrays.stream(String.class.getMethods()) |
List<String> mlist = new ArrayList<>(); |
val mlist = classOf[String].getMethods(). |
Excelのシート一覧取得 (POI) |
Workbook workbook = WorkbookFactory.create(new File(excelFile)); |
Workbook workbook =
WorkbookFactory.create(new File(excelFile)); |
val workbook = WorkbookFactory.create(new
File(excelFile)) |
val sheets =
for (i <- 0 until
workbook.getNumberOfSheets())
yield workbook.getSheetAt(i) |
Streamはオブジェクト(クラス)を対象としている。
プリミティブ型を対象とするStreamとして、専用のIntStream・LongStream・DoubleStreamが用意されている。
Stream<Integer>とIntStreamは意味的には同じかもしれないが、用意されているメソッドやintに対する処理速度は異なる。
ちなみにScalaの場合はIntもクラスなので、専用のクラスは無く、クラスとIntが同一に扱える。
それと、ストリームにはシーケンシャル(直列)なStreamとパラレル(並列)なStreamがある。
並列ストリームだと、(処理内容によっては)マルチスレッドで並列に処理される。
ただしオーバーヘッドはかかるので、対象件数が少ない場合は直列ストリームより遅くなることはある。
並列ストリームかどうかはisParallelメソッドを呼び出せば分かる。
並列ストリームを取得するにはparallelメソッドを、直列ストリームを取得するにはsequentialメソッドを呼び出す。
ストリームのメソッドは、動作内容に応じて中間処理と終端処理(末端処理)の2種類に分けられる。
おおまかに言うと、Streamを返すメソッドが中間処理で、それ以外は終端処理。
filter()やmap()等の処理を記述する(関数を渡す)メソッドは中間処理なので、“渡された関数を保持した新しいStream”を返す。
Stream内に保持されている値を使った演算は、中間処理では行わない。
forEach()やcollect()といった
終端処理のメソッドが呼ばれると、実際に処理を行う。
したがって、大量のデータを対象とするStreamの場合でも、実行時間がかかるのは終端処理であり、中間処理のメソッド呼び出しでは実行時間はほとんどかからない。
staticメソッド | 中間処理メソッド | 終端処理メソッド | その他 |
---|---|---|---|
|
|
Stream系のインターフェースは(インターフェースなので)newでインスタンスを作ることは出来ない。
Streamインスタンスを生成するメソッドが用意されているので、それを使う。
生成メソッド | 例 | 説明 | Scala相当 | ||
---|---|---|---|---|---|
生成方法 | 生成内容 | ||||
Stream IntStream LongStream DoubleStream |
of () |
Stream<String> s = Stream.of("abc",
"def"); |
abc, def |
初期値を指定して生成する。 | val s = Stream("abc", "def") |
IntStream s = IntStream.of(123, 456); |
123, 456 |
val s = Stream(123, 456) |
|||
ofNullable() |
Stream<String> s = Stream.ofNullable("abc"); |
abc |
Java9以降。[2017-09-24] 引数がnull以外の場合、その値を持つStreamを生成する。 引数がnullの場合は空のStreamを生成する。 |
||
empty () |
Stream<String> s = Stream.empty(); |
空のStreamを生成する。 | val s = Stream.empty[String] |
||
IntStream s = IntStream.empty(); |
val s = Stream.empty[Int] |
||||
builder () |
Builder<String> builder = Stream.builder(); |
abc, def |
ビルダーを使って生成する。 | ||
IntStream s = IntStream.builder().add(123).add(456).build(); |
123, 456 |
||||
iterate () |
Stream<String> s = Stream.iterate("a", c
-> c + c); |
a, aa, aaaa, … |
「前の値を使って新しい値を生成する関数」(UnaryOperator)を指定する。 第1引数は初期値。Streamの1つ目の値はこれになる。 2つ目以降の値は、1つ前の値を第2引数の関数に渡した結果となる。 このStreamは無限に続くので、limit()等を使って終了させる必要がある。 |
val s = Stream.iterate("a")(c => c + c) |
|
IntStream s = IntStream.iterate(1, n
-> n
* 2); |
1, 2, 4, 8, … |
val s = Stream.iterate(1)(_ * 2) |
|||
Stream<String> s = Stream.iterate("a", c
-> c.length() <= 4, c
-> c + c); |
a, aa, aaaa |
Java9以降。[2017-09-24] 終了条件付きiterate。 |
Stream.iterate("a")(c => c +
c).takeWhile(_.length <= 4) |
||
IntStream s = IntStream.iterate(1, n
-> n < 10, n
-> n * 2); |
1, 2, 4, 8 |
val s = Stream.iterate(1)(_ * 2).takeWhile(_ <
10) |
|||
generate () |
Stream<String> s = Stream.generate(()
->
"abc"); |
abc, abc, abc, … |
「値を返す関数」(Supplier)を指定する。 このStreamは無限に続くので、limit()等を使って終了させる必要がある。 |
val s = Stream.continually("abc") |
|
Random rnd = new Random(); |
3, 4, 2, 7, … |
val rnd = new Random |
|||
concat () |
Stream<String> s1 = Stream.of("a", "b"); |
a, b, x, y |
2つのStreamを結合する。 | val s1 = Stream("a", "b") |
|
IntStream s1 = IntStream.of(1, 2); |
1, 2, 8, 9 |
val s1 = Stream(1, 2) |
|||
Stream<String> s1 = 〜; |
3つ以上のStreamを結合する場合は、技巧的だがflatMapを使う方が綺麗かも?[2017-09-24] | val s1 = Stream(〜) |
|||
mapToInt(Integer::intValue) |
Stream<Integer> s = 〜; |
Stream<Integer>をIntStreamに変換する。[2017-04-11] IntStreamをStream<Integer>に変換するにはboxedを使う。 |
|||
IntStream LongStream |
range() |
IntStream s = IntStream.range(2, 6); |
2, 3, 4, 5 |
指定された範囲のStreamを生成する。 指定された末尾の値は含まない。 |
val s = 2 until 6 |
rangeClosed() |
IntStream s = IntStream.rangeClosed(2, 6); |
2, 3, 4, 5, 6 |
指定された範囲のStreamを生成する。 指定された末尾の値を含む。 |
val s = 2 to 6 |
|
コレクション (List・Queue・Set) |
stream () |
List<String> list = Arrays.asList("abc", "def"); |
abc, def |
コレクションから直列ストリームを生成する。 (Streamからコレクションを生成するにはcollect()(Collectors.toList等)を使う) |
val list = Seq("abc", "def") |
parallelStream () |
List<String> list = Arrays.asList("abc", "def"); |
abc, def |
コレクションから並列ストリームを生成する。 | val list = Seq("abc", "def") |
|
配列 | stream () |
String[] ss = { "abc", "def" }; |
abc, def |
配列から直列ストリームを生成する。 | val ss = Array("abc", "def") |
int[] ns = { 123, 456 }; |
123, 456 |
val ns = Array(123, 456) |
|||
String[] ss = { "a", "b", "c", "d", "e", "f" }; |
c, d, e |
val ss = Array("a", "b", "c", "d", "e", "f") |
|||
Spliterator [2015-12-12] |
Iterable<String> i = Arrays.asList("a", "b",
"c"); |
a, b, c |
SpliteratorからStreamを作ることが出来る。 (プリミティブStreamも対応している) |
他にも以下のクラス等にStreamを生成するメソッドが存在している。
Streamはオブジェクト(クラス)のデータを対象としている。
メソッド | 戻り型 | 引数 | 説明 | 例 | Streamなし相当 | Scala相当 | ||
---|---|---|---|---|---|---|---|---|
コーディング | 結果 | |||||||
filter |
Stream<T> |
(T) -> boolean |
predicate |
条件に一致したオブジェクトだけを抽出する。 条件判定の関数(Predicate)を渡す。 →filterの例 |
List<String> list = Arrays.asList("a", "bb",
"ccc"); System.out.println(list2); |
[bb] |
List<String> list = Arrays.asList("a", "bb", "ccc"); |
val list = Seq("a", "bb", "ccc") |
条件に一致しないオブジェクトを抽出する場合はPredicate.notを併用する。(Java11以降)[2018-10-01] | var stream = Stream.of("a", "", "c"); |
a |
val stream = Stream("a", "", "c") |
|||||
map |
Stream<R> |
(T) -> R |
mapper |
保持している値を変換する(値を変更した新しいStreamを返す)。 入力TをRに変換する関数(Function)を渡す。 (出力の型が入力の型(T)と同じでも構わない) →mapの例 |
List<String> slist = Arrays.asList("a.txt",
"b.txt"); |
[a.txt, b.txt] |
List<String> slist = Arrays.asList("a.txt", "b.txt"); |
val slist = Seq("a.txt", "b.txt") |
mapToInt |
IntStream |
(T) -> int |
mapper |
intに変換するmapメソッド。 入力Tをintに変換する関数(ToIntFunction)を渡す。 →mapToの例 |
List<String> list =
Arrays.asList("a", "bb", "ccc"); |
6 |
// mapToInt |
val list = Seq("a", "bb", "ccc") |
int len = 0; |
||||||||
mapToLong |
LongStream |
(T) -> long |
mapper |
longに変換するmapメソッド。 入力Tをlongに変換する関数(ToLongFunction)を渡す。 →mapToの例 |
||||
mapToDouble |
DoubleStream |
(T) -> double |
mapper |
doubleに変換するmapメソッド。 入力Tをdoubleに変換する関数(ToDoubleFunction)を渡す。 →mapToの例 |
||||
flatMap |
Stream<R> |
(T) -> Stream<R> |
mapper |
複数の値(0個も可)に変換するmapメソッド。 入力Tを複数個のRに変換する関数(Function)を渡す。 →flatMapの例
なお、flatMap内で作られたStreamは自動的にcloseされる。[2015-12-13] |
List<String> list = Arrays.asList("a2", "b0",
"c3"); |
[a, a, c, c, c] |
List<String> list = Arrays.asList("a2", "b0", "c3"); |
val list = Seq("a2", "b0", "c3") |
flatMapToInt |
IntStream |
(T) -> IntStream |
mapper |
intに変換するflatMapメソッド。 入力TをIntStreamに変換する関数(Function)を渡す。 |
||||
flatMapToLong |
LongStream |
(T) -> LongStream |
mapper |
longに変換するflatMapメソッド。 入力TをLongStreamに変換する関数(Function)を渡す。 |
||||
flatMapToDouble |
DoubleStream |
(T) -> DoubleStream |
mapper |
doubleに変換するflatMapメソッド。 入力TをDoubleStreamに変換する関数(Function)を渡す。 |
||||
mapMulti |
Stream<R> |
(T, Consumer<R>) -> void |
mapper |
(flatMapと同様に)複数の値に変換するメソッド。(Java16以降)[2021-03-21] 返したい値をconsumerに登録する形になっている。 →mapMultiの例 |
var stream = Stream.of("a2",
"b0", "c3"); |
[a, a, c, c, c] |
||
mapMultiToInt |
IntStream |
(T, IntConsumer) -> void |
mapper |
int(IntStream)に変換するmapMultiメソッド。(Java16以降)[2021-03-21] | ||||
mapMultiToLong |
LongStream |
(T, LongConsumer) -> void |
mapper |
long(LongStream)に変換するmapMultiメソッド。(Java16以降)[2021-03-21] | ||||
mapMultiToDouble |
DoubleStream |
(T, DoubleConsumer) -> void |
mapper |
double(DoubleStream)に変換するmapMultiメソッド。(Java16以降)[2021-03-21] | ||||
distinct |
Stream<T> |
重複した値を排除する。 重複の判定はObject#equals()で行われる。(実装上はLinkedHashMapなのでhashCode()も使われる[2018-07-15]) 順序のあるStreamの場合、データの並び順は変更されないことが保証されている。 (重複するデータがあった場合、最初のデータの位置が保持される) |
List<String> list = Arrays.asList("b", "a", "b",
"c", "a"); |
[b, a, c] |
List<String> list = Arrays.asList("b", "a", "b", "c", "a"); |
val list = Seq("b", "a", "b", "c", "a") |
||
sorted |
Stream<T> |
ソートする。 このメソッドを使う場合、保持されているデータはComparableを実装している必要がある。 |
List<String> list = Arrays.asList("c", "b", "d",
"a"); |
[a, b, c, d] |
List<String> list = Arrays.asList("c", "b", "d", "a"); |
val list = Seq("c", "b", "d", "a") |
||
sorted |
Stream<T> |
(T, T) -> int |
comparator |
ソートする。 比較関数(Comparator)を渡す。 |
List<String> list = Arrays.asList("aa", "b",
"ccc", "dd"); |
[b, aa, dd, ccc] |
List<String> list = Arrays.asList("aa", "b", "ccc", "dd"); |
val list = Seq("aa", "b", "ccc", "dd") |
peek |
Stream<T> |
(T) -> void |
action |
値を受け取る関数(Consumer)を渡す。 保持している値を関数に渡すが、出力Streamとしては何も変わらない。 デバッグ用途で、どんな値が入っているか確認したいとき等に使う。 →peekの例 |
Stream<String> s = Stream.of("a", "b", "c"); |
peek1=a |
||
limit |
Stream<T> |
long |
maxSize |
指定された個数までに限定する。 最大個数を渡す。 |
Stream<String> s = Stream.iterate("a", c
-> c + "b"); |
a |
val s = Stream.iterate("a")(c => c + "b") |
|
skip |
Stream<T> |
long |
n |
指定された個数の値をスキップ(除去)する。 スキップする個数を渡す。 |
Stream<String> s =
Stream.iterate("a", c
-> c + "b"); |
abb |
val s = Stream.iterate("a")(c => c + "b") |
|
takeWhile |
Stream<T> |
(T) -> boolean |
predicate |
Java9以降。[2017-09-24] 指定された条件を満たしている間、その値を取得する。 |
Stream<String> s =
Stream.iterate("a", c
-> c + "b"); |
a |
val s = Stream.iterate("a")(c => c + "b") |
|
dropWhile |
Stream<T> |
(T) -> boolean |
predicate |
Java9以降。[2017-09-24] 指定された条件を満たしている間、その値をスキップ(除去)する。 |
Stream<String> s =
Stream.iterate("a", c
-> c + "b"); |
abbb |
val s = Stream.iterate("a")(c => c + "b") |
|
gather |
Stream<R> |
Gatherer<T, ?, R> |
gatherer |
Java24以降。[2025-03-19] 中間処理を独自実装することが出来る。 →Gatherers |
メソッド | 戻り型 | 引数 | 説明 | 例 | Streamなし相当 | Scala相当 | ||
---|---|---|---|---|---|---|---|---|
コーディング | 結果 | |||||||
forEach |
void |
(T) -> void |
action |
値を処理する。 処理する関数(Consumer)を渡す。 副作用(値を表示したりとか)を起こす専用のメソッド。 並列ストリームの場合、処理順序や実行されるスレッドは保証されない。 処理を同期する必要があるのであれば、渡した関数の中で同期処理しなければならない。 →forEachの例 |
List<String> list = Arrays.asList("a", "b", "c"); |
value=a |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
forEachOrdered |
void |
(T) -> void |
action |
値を1つずつ順番に処理するforEachメソッド。(順序があるStreamの場合) ただし、実行されるスレッドは保証されない。 |
||||
toArray |
Object[] |
Object配列に変換する。 | Stream<String> s = Stream.of("a", "b", "c"); |
[a, b, c] |
val s = Stream("a", "b", "c") |
|||
toArray |
A[] |
(int) -> A[] |
generator |
配列に変換する。 配列インスタンスを生成する関数(IntFunction)を渡す。 |
Stream<String> s = Stream.of("a", "b", "c"); |
[a, b, c] |
val s = Stream("a", "b", "c") |
|
reduce |
T |
T |
identity |
値を集約する。 第1引数で初期値、第2引数で集約する関数(BinaryOperator)を渡す。 |
List<String> list =
Arrays.asList("a", "b", "c"); 順序は保証されないので、普通はStringのようなものには使わない。 |
1abc |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
(T, T) -> T |
accumulator |
|||||||
reduce |
Optional<T> |
(T, T) -> T |
accumulator |
値を集約する。 集約する関数(BinaryOperator)を渡す。 集約された値はOptionalに包まれて返ってくる。 Stream内に値が無い場合はOptional.emptyが返る。 |
List<String> list = Arrays.asList("a", "b", "c"); 順序は保証されないので、普通はStringのようなものには使わない。 |
Optional[abc] |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
reduce |
U |
U |
identity |
値を集約する。 初期値と集約する関数(BiFunction)と中間集約結果を最終結果にまとめる関数(BinaryOperator)を渡す。[/2017-02-25] |
class Result { |
24 |
List<Integer> list = Arrays.asList(1, 2, 3, 4); |
case class Result(m: Int, p: Int) ScalaのfoldLeftは先頭から順に処理するので、最終結果をまとめるような関数は不要。 |
(U, T) -> U |
accumulator |
|||||||
(U, U) -> U |
combiner |
|||||||
collect |
R |
() -> R |
supplier |
結果を作成する。 第1引数は結果を入れるオブジェクトを作成する関数。 第2引数はStream内の値を結果オブジェクトに入れる関数。 第3引数は結果オブジェクト同士をつないで1つの結果にする関数。 →collectの例 並列ストリームだと複数回supplierが呼ばれて 複数の中間結果オブジェクトが作られる可能性があり、 その場合はcombinerで結合する。 |
List<String> list =
Arrays.asList("a", "b", "c", "d"); |
abcd |
List<String> list = Arrays.asList("a", "b", "c", "d"); |
|
(R, T) -> void |
accumulator |
|||||||
(R, R) -> void |
combiner |
|||||||
collect |
R |
Collector<T, A, R> |
collector |
結果を作成する。 →Collector |
Stream<String> s = Stream.of("a", "b", "c"); |
[a, b, c] |
val s = Stream("a", "b", "c") |
|
toList |
List<T> |
不変Listを返す。(Java16以降)[2021-03-21] | Stream<String> s = Stream.of("a", "b", "c"); |
[a, b, c] |
val s = Stream("a", "b", "c") |
|||
min |
Optional<T> |
(T, T) -> int |
comparator |
最小値を返す。 比較関数(Comparator)を渡す。 空ストリームの場合はOptional.emptyが返る。 |
List<String> list = Arrays.asList("b", "a", "d",
"c"); |
Optional[a] |
List<String> list = Arrays.asList("b", "a", "d", "c"); |
val list = Seq("b", "a", "d", "c") |
max |
Optional<T> |
(T, T) -> int |
comparator |
最大値を返す。 比較関数(Comparator)を渡す。 空ストリームの場合はOptional.emptyが返る。 |
List<String> list = Arrays.asList("b", "a", "d",
"c"); |
Optional[d] |
List<String> list = Arrays.asList("b", "a", "d", "c"); |
val list = Seq("b", "a", "d", "c") |
count |
long |
要素数を返す。 | List<String> list = Arrays.asList("a", "b", "c"); |
3 |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
||
anyMatch |
boolean |
(T) -> boolean |
predicate |
1つでも条件に合致する値があればtrueを返す。 条件判定の関数(Predicate)を渡す。 条件に合致する値が見つかった時点で処理を終了する。(短絡評価。「 || 」相当)空ストリームの場合はfalseを返す。 |
List<String> list = Arrays.asList("a", "b", "c"); |
true |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
allMatch |
boolean |
(T) -> boolean |
predicate |
全ての値が条件に合致したらtrueを返す。 条件判定の関数(Predicate)を渡す。 条件に合致しない値が見つかった時点で処理を終了する。(短絡評価。「 && 」相当)空ストリームの場合はtrueを返す。 |
List<String> list = Arrays.asList("a", "b", "c"); |
true |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
noneMatch |
boolean |
(T) -> boolean |
predicate |
条件に合致する値が1つもなかったらtrueを返す。 条件判定の関数(Predicate)を渡す。 条件に合致する値が見つかった時点で処理を終了する。(短絡評価) 空ストリームの場合はtrueを返す。 |
List<String> list = Arrays.asList("a", "b", "c"); |
true |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
findFirst |
Optional<T> |
先頭の値を返す。 空ストリームの場合はOptional.emptyを返す。 |
List<String> list = Arrays.asList("a", "b", "c"); |
Optional[a] |
List<String> list = Arrays.asList("a", "b", "c"); |
val list = Seq("a", "b", "c") |
||
findAny |
Optional<T> |
ストリーム内のいずれかの値を返す。 空ストリームの場合はOptional.emptyを返す。 |
List<String> list = Arrays.asList("a", "b", "c"); |
Optional[a] |
BaseStreamは、Stream系インターフェースに共通なメソッドを宣言しているインターフェース。
メソッド | 戻り型 | 引数 | 説明 | 例 | Scala相当 | ||
---|---|---|---|---|---|---|---|
コーディング | 結果 | ||||||
sequential |
Stream |
直列ストリームを返す。 | Stream<String> s = Stream.of("a"); |
false |
val s = Stream("a") |
||
parallel |
Stream |
並列ストリームを返す。 →isParallelメソッド |
Stream<String> s = Stream.of("a"); |
true |
val s = Stream("a") |
||
unordered |
Stream |
順序を持たないストリームを返す。 | Stream<String> s = Stream.of("a"); |
||||
onClose |
Stream |
() -> void |
closeHandler |
クローズ時に呼ばれるハンドラーを登録する。 →closeメソッド (closeを明示的に呼ばないとonCloseは呼ばれないので注意。[2015-12-13]) |
Stream<String> s = Stream.of("a") |
メソッド | 戻り型 | 引数 | 説明 | 例 | Scala相当 | ||
---|---|---|---|---|---|---|---|
コーディング | 結果 | ||||||
iterator |
Iterator<T> |
イテレーターを返す。 (→Iterableに変換してfor-each文を使う例[2019-11-28]) |
Stream<String> s = Stream.of("a",
"b"); |
a |
val s = Stream("a", "b") |
||
spliterator |
Spliterator<T> |
Streamを作成するのに使う。[2015-12-12] →StreamSupport |
メソッド | 戻り型 | 引数 | 説明 | 例 | Scala相当 | ||
---|---|---|---|---|---|---|---|
コーディング | 結果 | ||||||
isParallel |
boolean |
並列ストリームかどうかを返す。 →sequentialメソッド・parallelメソッド |
Stream<String> s = Stream.of("a").parallel(); |
true |
val s = Stream("a").par |
||
close |
void |
ストリームをクローズする。 具体的には、onCloseメソッドで登録されたハンドラーを呼び出す。 クローズ後に他の処理を実行することは出来ない。 BaseStreamはAutoCloseableを継承しているので、リソース付きtry文も使える。 |
try
(Stream<String> s = Stream.of("a", "b").onClose(()
-> { |
a |
Streamとは別に、intを扱うIntStream、longを扱うLongStream、doubleを扱うDoubleStreamがある。
Streamと同名のメソッドであれば処理内容は同等だが、引数や戻り値の型がプリミティブ用になっている。
メソッド | IntStream | LongStream | DoubleStream | 説明 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
戻り型 | 引数 | 戻り型 | 引数 | 戻り型 | 引数 | |||||
filter |
IntStream |
(int) -> boolean |
predicate |
LongStream |
(long) -> boolean |
predicate |
DoubleStream |
(double) -> boolean |
predicate |
|
map |
IntStream |
(int) -> int |
mapper |
LongStream |
(long) -> long |
mapper |
DoubleStream |
(double) -> double |
mapper |
|
mapToObj |
Stream<U> |
(int) -> U |
mapper |
Stream<U> |
(long) -> U |
mapper |
Stream<U> |
(double) -> U |
mapper |
値をオブジェクトに変換する。 |
mapToInt |
IntStream |
(long) -> int |
mapper |
IntStream |
(double) -> int |
mapper |
値をintに変換する。 | |||
mapToLong |
LongStream |
(int) -> long |
mapper |
LongStream |
(double) -> long |
mapper |
値をlongに変換する。 | |||
mapToDouble |
DoubleStream |
(int) -> double |
mapper |
DoubleStream |
(long) -> double |
mapper |
値をdoubleに変換する。 | |||
flatMap |
IntStream |
(int) -> IntStream |
mapper |
LongStream |
(long) -> LongStream |
mapper |
DoubleStream |
(double) -> DoubleStream |
mapper |
|
mapMulti |
IntStream |
(int, IntConsumer) -> void |
mapper |
LongStream |
(long, LongConsumer) -> void |
mapper |
DoubleStream |
(double, DoubleConsumer) -> void |
mapper |
Java16以降。[2021-03-21] |
distinct |
IntStream |
LongStream |
DoubleStream |
|||||||
sorted |
IntStream |
LongStream |
DoubleStream |
|||||||
peek |
IntStream |
(int) -> void |
action |
LongStream |
(long) -> void |
action |
DoubleStream |
(double) -> void |
action |
|
limit |
IntStream |
long |
maxSize |
LongStream |
long |
maxSize |
DoubleStream |
long |
maxSize |
|
skip |
IntStream |
long |
n |
LongStream |
long |
n |
DoubleStream |
long |
n |
|
takeWhile |
IntStream |
(int) -> boolean |
predicate |
LongStream |
(long) -> boolean |
predicate |
DoubleStream |
(double) -> boolean |
predicate |
Java9以降。[2017-09-24] |
dropWhile |
IntStream |
(int) -> boolean |
predicate |
LongStream |
(long) -> boolean |
predicate |
DoubleStream |
(double) -> boolean |
predicate |
Java9以降。[2017-09-24] |
asLongStream |
LongStream |
LongStreamを返す。 | ||||||||
asDoubleStream |
DoubleStream |
DoubleStream |
DoubleStreamを返す。 | |||||||
boxed |
Stream<Integer> |
Stream<Long> |
Stream<Double> |
ラッパークラスのStreamを返す。 逆変換はmapToInt等を使う。 |
メソッド | IntStream | LongStream | DoubleStream | 説明 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
戻り型 | 引数 | 戻り型 | 引数 | 戻り型 | 引数 | |||||
forEach |
void |
(int) -> void |
action |
void |
(long) -> void |
action |
void |
(double) -> void |
action |
|
forEachOrdered |
void |
(int) -> void |
action |
void |
(long) -> void |
action |
void |
(double) -> void |
action |
|
toArray |
int[] |
long[] |
double[] |
|||||||
reduce |
int |
int |
identity |
long |
long |
identity |
double |
double |
identity |
|
(int, int) -> int |
op |
(long, long) -> long |
op |
(double, double) -> double |
op |
|||||
reduce |
OptionalInt |
(int, int) -> int |
op |
OptionalLong |
(long, long) -> long |
op |
OptionalDouble |
(double, double) -> double |
op |
|
collect |
R |
() -> R |
supplier |
R |
() -> R |
supplier |
R |
() -> R |
supplier |
|
(R, int) -> void |
accumulator |
(R, long) -> void |
accumulator |
(R, double) -> void |
accumulator |
|||||
(R, R) -> void |
combiner |
(R, R) -> void |
combiner |
(R, R) -> void |
combiner |
|||||
sum |
int |
long |
double |
合計値を算出する。 | ||||||
min |
OptionalInt |
OptionalLong |
OptionalDouble |
最小値を取得する。 | ||||||
max |
OptionalInt |
OptionalLong |
OptionalDouble |
最大値を取得する。 | ||||||
count |
long |
long |
long |
要素数を取得する。 | ||||||
average |
OptionalDouble |
OptionalDouble |
OptionalDouble |
平均値を算出する。 | ||||||
summaryStatistics |
IntSummary |
LongSummary |
DoubleSummary |
要素数・合計値・最小値・最大値・平均値を取得する。 | ||||||
anyMatch |
boolean |
(int) -> boolean |
predicate |
boolean |
(long) -> boolean |
predicate |
boolean |
(double) -> boolean |
predicate |
|
allMatch |
boolean |
(int) -> boolean |
predicate |
boolean |
(long) -> boolean |
predicate |
boolean |
(double) -> boolean |
predicate |
|
noneMatch |
boolean |
(int) -> boolean |
predicate |
boolean |
(long) -> boolean |
predicate |
boolean |
(double) -> boolean |
predicate |
|
findFirst |
OptionalInt |
OptionalLong |
OptionalDouble |
|||||||
findAny |
OptionalInt |
OptionalLong |
OptionalDouble |
Streamでは、Streamクローズ時の処理をonCloseメソッドによって指定できる。[2015-12-13]
ファイルをオープンする等のStreamでは、onCloseでファイルをクローズするような使い方がされている。
public static Stream<String> lines(Path path, Charset cs) throws IOException { BufferedReader br = Files.newBufferedReader(path, cs); try { return br.lines().onClose(asUncheckedRunnable(br)); } catch (Error|RuntimeException e) { try { br.close(); } catch (IOException ex) { try { e.addSuppressed(ex); } catch (Throwable ignore) {} } throw e; } }
ただし、onCloseが呼ばれるのは、Streamがクローズされた場合である。
つまり、closeメソッドが呼ばれた際にonCloseが呼ばれる。
(StreamはAutoCloseableを実装しているのでcloseメソッドを持っており、try-with-resources構文が使える)
そして、終端処理(forEachメソッド等)を実行しただけではcloseメソッドは呼ばれない。closeメソッドは自分で呼び出す必要がある。
したがって、Files.lines()を使う例だと、明示的にクローズする使い方が正しい。
正 | 誤 |
---|---|
try(Stream<String> s = Files.lines(Path)) { s.forEach(System.out::println); } |
Stream<String> s = Files.lines(Path)); s.forEach(System.out::println); |
なお、作られたStreamがonCloseを使っているかどうかを知る方法は無い(と思う)ので、返されたStreamをクローズすべきかどうかはメソッド毎に注意する必要がある。
(全てのStreamに対して必ずクローズを呼び出せば大丈夫ではありそう^^;)
flatMapメソッドを使う場合、flatMap内で作られたStreamは自動的にクローズされる。
(全体のStreamがクローズされるかどうかとは無関係に、そのStreamが使い終わった時点でクローズされるようだ)
最終クローズあり | 最終クローズなし | |
---|---|---|
例 |
static Stream<String> create() { return Stream.of(Arrays.asList("a", "b", "c"), Arrays.asList("d", "e")) .onClose(() -> System.out.println("close2")) .flatMap(list -> list.stream().onClose(() -> System.out.println("close1"))); } |
|
try (Stream<String> s = create()) { s.forEach(System.out::println); } |
Stream<String> s = create(); s.forEach(System.out::println); |
|
実行結果 | a |
a |