9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Java8 Lambdaまとめ その2

Last updated at Posted at 2015-08-14

続きです

sumを使ったList内部の計算

List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);

System.out.println(intList);

Long count = intList.stream().mapToLong(value -> Integer.toUnsignedLong(value)).sum();

System.out.println(count);

最初のまとめでは説明を省略しましたが、末端処理のsumを使ってList内部の計算になります。
sumはIntStream LongStream DoubleStreamでのみ呼び出し可能な末端処理となっていますので、中間処理完了時点で型を合わせてあげる必要がある点に注意が必要です。
mapToXXXはそのような形に変換してくれるので、今回はそれを使いました。

List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);

System.out.println(intList);

Long count = intList.stream().map(value -> value).mapToLong(value -> Long.valueOf(value)).sum();

System.out.println(count);

mapは中間処理なので、複数繋げて何回もリストの変換を行うことも可能なので、ほとんどのケースはこれでいけそうな感じがします。

List内部の要素を取得

前回はmatchする形での取得を書きましたが、今回はListの最初の要素など決まった要素を取得する形について書きます。

List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);

System.out.println(intList);

Integer count = intList.stream().findFirst().get();

System.out.println(count);

List内の最初の要素を取得する場合は末端処理のfindFirstを使用します。
見つかった最初の要素を取得することが出来ます。

List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);

System.out.println(intList);

Integer count = intList.stream().findAny().get();

System.out.println(count);

List内のランダム要素を取得する場合は、findAnyを使えば取れるらしいのですが、実行すると最初しか取れなかったのでちょっと良く分からないなーというしかありません。

List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);

System.out.println(intList);

Integer count = intList.stream().reduce((base, value) -> value).get();

System.out.println(count);

また、findLastはないので、Listの最後の要素を取りたいという場合にはfindは出来ません(なんてこったい)。
色々やり方を調べてみたのですが、reduceを使って、現在の値を返却し続けるというのが一番楽に実装出来そうです(300万件のListから最後のリストを取得するという処理で性能をはかりましたが、100msもかからなかったので性能的にも問題なさそうです)

Streamで色々処理した後の個数を取得する

いわゆるcountを計測する方法です。
変換後の値も使用したい場合は、中間処理を終わった段階のStreamを保持して、末端処理をいくつも書くのが良いと思います。

List<String> stringList = new ArrayList<String>();
stringList.add("japan");
stringList.add("usa");
stringList.add("england");

int count = stringList.stream().collect(Collectors.toList()).size();

System.out.println(count);

collectしてからsizeで取り出しても良いですが

List<String> stringList = new ArrayList<String>();
stringList.add("japan");
stringList.add("usa");
stringList.add("england");

int count = stringList.stream().count();

System.out.println(count);

末端処理としてcountが定義されているので、これを使うと簡単に要素数が取得出来ます。

From Map to List

Map<String, String> stringMap = new HashMap<String, String>();
stringMap.put("japan", "japanese");
stringMap.put("usa", "english");
stringMap.put("england", "english");

List<String> list = stringMap.entrySet().stream().map(entry -> entry.getKey()).collect(Collectors.toList());

System.out.println(list);

Map<K,V>からList<T>への変換は簡単です。entrystreamを取得してmapするだけです。その際の引数はentryになるので、そこだけ注意が必要です。
たまに(key, value)とかやってはまるバカがここにいます。

拡張for文ではなく普通のfor文を変換する

java7
for(int i = 0; i < 5; i++) {
    System.out.println(i);
}

よくある数値を使ってのループもラムダ(正確にはStream)を使うと変換することが出来ます。

java8
Stream.iterate(0, i -> i + 1).limit(5).forEach(System.out::println);

StreamのClass内にiterateというstaticメソッドがあり、それを使うことで実現可能になります。
このメソッドは<T>型の無限のシーケンシャルStreamを作ってくれます。
第一引数に初期値(seed)(position 0の要素)が入ります。
第二引数は(無限に)繰り返して呼ばれ、returnした値が呼ばれた順番の要素になります。Lambdaでの引数は1個前の要素が入ってきます。
上の例ではHaskellの[0..4]と同様の結果を得る事が出来るStreamとなっています。

無限なので、作った後にきちんと使う所だけを抽出してあげないといけないのですが、filterではうまく上の例を表現できなかったので、現状ではlimitを使って個数を制限した方が良いという結論です。他の中間処理をさせたい場合も先にlimitしてからの方が効率的だと思います。

最後に

便利なstreamといえども、出来ない事もあるので、きちんと使えるケースを把握しておかないとたまにはまります。
そうなると勿体ないので、しっかりケースを把握していければ強力なstreamが味方になってくれて助かるのかと思ってます。
まだ新しく書くことがどんどん出てきている状況ですが、その3作るのも面倒なのである程度はここに追記されていきます。

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?