次に、集計結果を返したり要素を使って処理を実行したりする最終的な処理を行うメソッドを見てみましょう。Streamのメソッドの中で結果を返すものの中に処理結果を格納した「Optional」というクラスを返すものがあります。
まずは、その戻り値となるOptionalについて見ていきましょう。
本稿のOptionalクラスの使い方について一部読者から指摘があり、内容を補足させていただきました。
Optionalとは値を格納するクラスです。主な使い方としてはStream APIの最終的なメソッドの処理結果としてOptionalが返されます。
そして、Optional#getメソッドを使って格納された値を受け取ります。このとき、Optionalの値がない場合は例外が発生します。値があるかどうか確認するにはOptional#isPresentメソッドを使って確認します。Optional#isPresentメソッドの戻り値がtrueの場合は値があると判断できます。以下、Optionalの主なメソッドです。
戻り値 | メソッド | 概要 |
---|---|---|
T | get() | Optional<T>で格納している値を返す。格納している値がない場合はNoSuchElementExceptionの例外が発生 |
boolean | isPresent() | 値が格納されている場合はtrue、格納されていない場合はfalseを返す |
T | orElse(T other) | 値が格納されている場合はその値を返し、格納されていない場合は引数のotherを返す |
T | orElseGet(Supplier<? extends T> supplier) | 値が格納されている場合はその値を返し、格納されていない場合はsupplierが生成した値を返す |
T | orElseThrow(Supplier<? extends Throwable> supplier) | 値が格納されている場合はその値を返し、格納されていない場合はsupplierが発生させる例外を生成する |
Optional<T> | of(T value) | Optionalのstaticなメソッド。引数のvalueを格納したOptionalを返す。引数のvalueはnullでないものしか設定しないようにする。valueがnullの場合、Optional#getメソッドで値を取得する際に例外が発生 |
Optional<T> | ofNullable(T value) | Optionalのstaticなメソッド。引数のvalueがnullでない場合、そのvalueを格納したOptionalを返す。nullの場合はOptional#emptyメソッドで生成されるOptionalを返す |
Optional<T> | empty() | Optionalのstaticなメソッド。値が格納されていないOptionalを返す |
void | ifPresent(Consumer<? super T> consumer) | Optionalが値を格納している場合はconsumerの処理を実行し、OptionalがEmptyの場合は何もしない |
Optional<U> | map(Function<? super T, ? super U> function | Optionalが持つTの型を持つ値からfunctionによりUの型を持つ値を生成し、そのUの型の値を持つOptionalを返す |
Optional<T> | filter(Predicate<? super T> predicate) | Optionalがpredicateによる判定でtrueの場合、Optionalに何も変化はなく、判定がfalseの場合、OptionalはEmptyになります。 |
// String"あ"を格納したOptionalから、その値を取得しています System.out.println("Optional.of(\"あ\").get()=" + Optional.of("あ").get()); // Optionalに値が存在する場合はTrueを返します System.out.println("Optional.of(\"あ\").isPresent()=" + Optional.of("あ").isPresent()); System.out.println("Optional.empty().isPresent()=" + Optional.empty().isPresent()); // Optionalに値があればその値を、なければorElseで指定した値を返します System.out.println("Optional.of(\"あ\").orElse(\"い\")=" + Optional.of("あ").orElse("い")); System.out.println("Optional.empty().orElse(\"い\")=" + Optional.empty().orElse("い")); // Optionalに値があればその値を、なければSupplierが生成した値を返します System.out.println("Optional.of(\"あ\").orElseGet(()->\"う\")=" + Optional.of("あ").orElseGet(()->"う")); System.out.println("Optional.empty().orElseGet(()->\"う\")=" + Optional.empty().orElseGet(()->"う")); // Optionalに値がなければ指定した例外をThrowします try{ Optional.empty().orElseThrow(()->new Exception("自作の例外")); } catch (Exception e){ System.out.println(e); } // 引数の値がNullでなければその値を格納したOptionalを、NullならemptyなOptionalを返します System.out.println("Optional.ofNullable(\"あ\")=" + Optional.ofNullable("あ")); System.out.println("Optional.ofNullable(null)=" + Optional.ofNullable(null)); // Optionalに値がある場合、ifPresentの処理が実行されます System.out.println("ifPresentの例(値がある場合):"); Optional.of("あ").ifPresent(value -> System.out.println("value=" + value)); // Optionalの値がEmptyの場合、ifPresentの処理は実行されません System.out.println("ifPresentの例(値がない場合):"); Optional.empty().ifPresent(value -> System.out.println("value=" + value)); System.out.println("何も実行されません"); // Optionalの値から別の値を生成したOptionalを返します。 System.out.println("Optional<BigDecimal> bigDecimalOptional = Optional.of(\"12345\").map(value -> new BigDecimal(value))"); Optional<String> stringOptional = Optional.of("12345"); Optional<BigDecimal> bigDecimalOptional = stringOptional.map(value -> new BigDecimal(value)); BigDecimal result = bigDecimalOptional.get(); System.out.println("BigDecimal result = bigDecimalOptional.get()"); System.out.println("result=" + result); System.out.println("result.getClass()=" + result.getClass()); // filterの結果がTrueの場合はそのままのOptionalを返します System.out.println("Optional.of(new BigDecimal(\"1\")).filter(value -> value.compareTo(BigDecimal.ZERO) > 0)=" + Optional.of(new BigDecimal("1")).filter(value -> value.compareTo(BigDecimal.ZERO) > 0)); // filterの結果がFalseの場合はEmptyなOptionalを返します System.out.println("Optional.of(new BigDecimal(\"1\")).filter(value -> value.compareTo(BigDecimal.TEN) > 0)=" + Optional.of(new BigDecimal("1")).filter(value -> value.compareTo(BigDecimal.TEN) > 0));
Optional.of("あ").get()=あ Optional.of("あ").isPresent()=true Optional.empty().isPresent()=false Optional.of("あ").orElse("い")=あ Optional.empty().orElse("い")=い Optional.of("あ").orElseGet(()->"う")=あ Optional.empty().orElseGet(()->"う")=う java.lang.Exception: 自作の例外 Optional.ofNullable("あ")=Optional[あ] Optional.ofNullable(null)=Optional.empty ifPresentの例(値がある場合): value=あ ifPresentの例(値がない場合): 何も実行されません Optional<BigDecimal> bigDecimalOptional = Optional.of("12345").map(value -> new BigDecimal(value)) BigDecimal result = bigDecimalOptional.get() result=12345 result.getClass()=class java.math.BigDecimal Optional.of(new BigDecimal("1")).filter(value -> value.compareTo(BigDecimal.ZERO) > 0)=Optional[1] Optional.of(new BigDecimal("1")).filter(value -> value.compareTo(BigDecimal.TEN) > 0)=Optional.empty
またOptionalもStreamと同様にプリミティブ型の数値を要素として扱うためのものが用意されています。次のものが拡張されたOptionalです。
Optionalの種類 | 概要 |
---|---|
OptionalInt | int値を格納するOptional |
OptionalLong | long値を格納するOptional |
OptionalDouble | double値を格納するOptional |
次はStreamが持つ要素を取得するメソッドを見てみましょう。以下は主なものです。
戻り値 | メソッド | 概要 |
---|---|---|
Optional<T> | max(Comparator<? super T> comparator) | 要素の中で最大のものを返す。大小の比較には引数のcomparatorを使う。要素がなかった場合はemptyなOptionalを返す |
Optional<T> | min(Comparator<? super T> comparator) | 要素の中で最小のものを返す。大小の比較には引数のcomparatorを使う。要素がなかった場合はemptyなOptionalを返す |
Optional<T> | findFirst() | 要素の中で最初の要素を返す。要素がなかった場合はemptyなOptionalを返す |
Optional<T> | findAny() | 要素の中の1つの要素を返す。要素がなかった場合はemptyなOptionalを返す |
List<BigDecimal> list = new ArrayList<>(); list.add(new BigDecimal(3)); list.add(new BigDecimal(4)); list.add(new BigDecimal(5)); list.add(new BigDecimal(1)); list.add(new BigDecimal(2)); // 最大値の取得 Optional<BigDecimal> max = list.stream().max((a, b) -> a.compareTo(b)); System.out.println("max: " + max); // 最小値の取得 Optional<BigDecimal> min = list.stream().min((a, b) -> a.compareTo(b)); System.out.println("min: " + min); // 要素の最初のものを取得 Optional<BigDecimal> first = list.stream().findFirst(); System.out.println("first: " + first); // 要素の中のどれか1つを取得 Optional<BigDecimal> any = list.stream().findAny(); System.out.println("any: " + any);
max: Optional[5] min: Optional[1] first: Optional[3] any: Optional[3]
次はStreamの各要素を受け取り、それを使って処理をするメソッドを見てみましょう。主なものは次のものになります。
戻り値 | メソッド | 概要 |
---|---|---|
void | forEach(Consumer<? super T> consumer) | Streamの各要素をconsumerが引数として受け取り、処理を行う。並列処理で使った場合、元データがListのような集合体でも順番を保障しない |
void | forEachOrdered(Consumer<? super T> consumer) | Streamの各要素が順番を担保している場合、その各要素をconsumerが順番通り引数として受け取り、処理を行う |
forEachの例は他のサンプルでも既に使っているので、ここでは並列処理の場合で見てみましょう。並列処理の場合、forEachメソッドは順番が保障されませんがforEachOrdedメソッドの場合はlistの順番が保たれます。
List<String> list = Arrays.asList(new String[]{"あ", "い", "う", "え", "お"}); Stream<String> parallelStream1 = list.parallelStream(); parallelStream1.forEach(value -> System.out.println("forEach: " + value)); Stream<String> parallelStream2 = list.parallelStream(); parallelStream2.forEachOrdered(value -> System.out.println("forEachOrdered: " + value));
forEach: う forEach: あ forEach: え forEach: い forEach: お forEachOrdered: あ forEachOrdered: い forEachOrdered: う forEachOrdered: え forEachOrdered: お
Copyright © ITmedia, Inc. All Rights Reserved.