LoginSignup
8
9

More than 3 years have passed since last update.

5分で分るJava Stream API

Last updated at Posted at 2019-07-29

この記事ではJava Stream APIが読めない人を対象にしています。

以下の人にオススメです

  • Javaとか昔は書いてたけど最近は書いてない
  • Stream APIが読めなくてコーディングを辞めた
  • とにかく時間がないから勘所だけ知りたい

最初に

Java Stream APIとは、 InputStreamや、OutputStreamなどのI/Oクラスとは関係ありません。
List,SetなどのCollection Object,または配列などのループ可能な要素をループの中で一度だけ処理する仕組みの事を言います。
※Streamは一度処理すると再利用できません。ただし、Streamはchain(連鎖)させることで複数の処理が可能です。

Stream APIを利用して行うものは、よく使うのは以下の2点です

  • エンティティを変換する(mapメソッド)
  • コレクションをフィルターする(filterメソッド)

Javaのコードを記載します。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamTest {
    public static void main(String[] args) {
        List<String> csvList = new ArrayList<>();
        csvList.add("田中 直樹,MAN");
        csvList.add("北村 一輝,MAN");
        csvList.add("加藤 しずか,WOMAN");
        csvList.add("小野 妹子,UNKNOWN");
        // 1.エンティティを変換する。(map)
        List<Person> persons = csvList.stream().map(Person::convertPersonFromCSV).collect(Collectors.toList());

        // 2.エンティティをフィルターする。(filter)
        List<Person> mens = persons.stream().filter(p -> p.getGender() == Gender.MAN).collect(Collectors.toList());

        System.out.println("Print all persons");
        persons.forEach(System.out::println);

        System.out.println("Print mens only");
        mens.forEach(p -> System.out.println(p.getName()));
    }

    enum Gender {
        MAN,
        WOMAN,
        UNKNOWN;
    }

    static class Person {
        private String name;
        private Gender gender;

        public Person(String name, Gender gender) {
            this.name = name;
            this.gender = gender;
        }

        @Override
        public String toString() {
            return String.format("My name is %s . \r\nMy gender is %s.", name, gender);
        }

        public String getName() {
            return this.name;
        }

        public Gender getGender() {
            return this.gender;
        }

        public static Person convertPersonFromCSV(String csv) {
            String[] csvStrings = csv.split(",");
            if (csvStrings.length != 2) throw new IllegalArgumentException("csv is illegal format.");
            return new Person(csvStrings[0], Gender.valueOf(csvStrings[1]));
        }
    }
}

それでは、順番に上記を見ていきましょう

エンティティを変換する

エンティティを変換する際は、mapメソッドを使用します。
mapメソッドで変換、collectメソッドでStreamを再度Collection型に変換します。

主に以下の3種類の書き方が出来ます。

csvList.stream().map(Person::convertPersonFromCSV).collect(Collectors.toList());
csvList.stream().map(csv -> Person.convertPersonFromCSV(csv)).collect(Collectors.toList());
csvList.stream().map(csv -> {
                         Person person = Person.convertPersonFromCSV(csv);
                         return person;
                     }).collect(Collectors.toList());

どれもやっていることは同じで、csvListの要素であるStringを取得して、
Personオブジェクトに変換して返却するメソッドを実行しています。

  • 1番目は引数のcsvを省略する書き方
  • 2番目はreturnメソッドを省略して1行で記述する書き方
  • 3番目は何も省略しない書き方

Streamを使うことで、Listを1行(ワンライナー)でListに変換することが出来ました。
Streamを使用することのメリットの一つとして、コードの記述量を減らすことが出来るというものがあります。

以下は時間のない人は飛ばしてください。

  • csvList.stream()
    • Streamオブジェクトを取得します。
  • map(Person::convertPersonFromCSV)
    • mapメソッドの引数として、csvListのGenericインターフェースであるStringが与えられます。
    • Personクラスのエンティティ変換メソッドを呼び出しentityの変換を行い、entityクラスを返却します。
    • Functionインターフェースを実装したメソッドを使用して、StringクラスをPersonクラスに変換して返却しています。
  • collect(Collectors.toList())
    • 変換されたPersonを集めます。
    • Collectors.toList()でListクラスに追加していきます。
    • Collectors.toXXX()でSetやMapにも変換できます。toMapの場合、keyとvalueを返却する2つのFunctionを記述する必要があります。
  • メソッドの処理の順序としては、「mapで変換,collectでStreamで処理したオブジェクトをリストに格納」という処理を繰り返すイメージとなります。

コレクションをフィルターする

コレクションから特定の要素を除外して、新しいコレクションオブジェクトを作成することが出来ます。
filterメソッドを使用して、残したい対象のオブジェクトを記載します。

persons.stream().filter(p -> p.getGender() == Gender.MAN).collect(Collectors.toList());

Streamを使うことで、Listから男性のみを抽出した新しいコレクションをワンライナーで作成できました。

  • filter(p -> p.getGender() == Gender.MAN)
    • Personを引数に取り、booleanを返却します。

Stream APIを使用してよくやる他のこと

  • findAny
    • filterと組み合わせて、特定の要素が存在するかどうかを検出する。
  • sum
    • mapToIntと組み合わせて、コレクションの合計数を算出する。
  • reduce
    • コレクションの要素を結合して一つのオブジェクトに纏める。
8
9
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
8
9