web-dev-qa-db-ja.com

Java8:ストリームの最初の結果

findFirst().get()を使用せずに.orElse()で警告を取り除く方法があることを知りたいNoSuchElementException。たとえば、次のコードを見てみましょう。

_    List<String> myList = new ArrayList<>();
    myList.add("Test");
    myList.add("Example");
    myList.add("Sth");

    String fisrstString = myList.stream().findFirst().get(); // here I surely get "Test" 
_

私は他のIDE-sがこれをどのように扱うのかわかりませんが、私のIDE(IntelliJ)はそれを警告('Optional.get()' without 'isPresent()')として扱います。いつNoSuchElementExceptionが得られるのか、いつ得られないのか、またはその理由がわからない。この警告を解決する方法があることは知っている(isPresent() check、.orElse(something) )しかし、役に立たないコードでは、単純にそれらのソリューションは必要ないので使用したくないのですが、何ができるのか、IDEによってどのように扱われるのか説明がありますか?

編集: NPEでごめんなさい、そのNoSuchElementException私はそのエラーがありましたが、質問はまだ利用できると思います。

14
Sunflame

私にとっては、関数型プログラミングを使用して、オプションで引き続き作業することが最善の方法です。したがって、たとえば、この文字列を何らかのサービスに渡す必要がある場合は、次のことができます。

String fisrstString = myList.stream().findFirst().get();
service.doSomething(fisrstString);

しかし、これはあまり良くありません。代わりに、関数型プログラミングの長所を使用して、以下を実行できます。

myList.stream().findFirst().ifPresent(service::doSomething);
14
Sergii Bishyr

最初にNPEを取得するのではなく、NoSuchElementExceptionを取得します。第二に、それはyoだれが確かかもしれません;しかし、他の人々がやって来て、それをwill例外をスローしないことに気付かないかもしれません。

サンドボックスプロジェクトの場合-はい、気にしないで警告を無視できます。量産コードの場合は、無効にすることはできません(できたとしても)。

そして最後のポイントは、あなたがそう確信しているなら、なぜ例外を投げないのかということです。

orElseThrow(IAmSureThisWillNotHappenException::new)
8
Eugene

(実際に存在する場合)値を取得しようとする代わりに、findFirst()によって返されるOptionalを使用する必要があります。

myList.stream()
    .findFirst()
    .ifPresent(/* consume the string here, if present */);

Optional.ifPresent メソッドは、[ Consumer を受け取ります。これは、OptionalにNULL以外の値が含まれる場合にのみ使用されます。

問題は、我々がJava開発者は命令型パラダイムにとても慣れているということです...特に、オブジェクトを取得し、pushingit itメソッドへ:

String myString = "hello"; // getting an object here

System.out.println(myString); // pushing the object to System.out here
                              // (via the println method)

Stream.findFirst()によって返されるOptionalを使用すると、上記と同じことをしていました。

String myString = myList.stream()
    .findFirst()
    .get(); // getting a string here

System.out.println(myString); // pushing the string here

一方、機能パラダイム(Optionalを含む)は通常、他の方法で機能します。

myList.stream()
    .findFirst()
    .ifPresent(myString -> System.out.println(myString));

ここでは、文字列を取得せずに、それを何らかのメソッドにプッシュします。代わりに、OptionalifPresent操作に引数を指定し、Optionalの実装に値を引数にプッシュさせます。つまり、Optionalの引数を使用して、ifPresentでラップされた値をpullします。 ifPresentは、値が存在する場合にのみ、このConsumer引数を使用します。

このプルパターンは関数型プログラミングでよく見られ、慣れると非常に便利です。開発者が別の方法で思考(およびプログラミング)を開始する必要があります。

問題なく空のリストをストリーミングできますが、空のリストの最初の要素を取得しようとするとNoSuchElementExceptionが返されます

stream APIはその問題を認識しているため、複数の方法で処理できます。

Option1orElse最初の要素が見つからない場合は「デフォルト」値を返すことができます

String firstString = myList.stream().findFirst().orElse("Ups!");

Option2orElseGetを使用できますSupplier<String>最初の要素が見つからない場合に文字列を返します

firstString = myList.stream().findFirst().orElseGet(mySupplier);

OptionorElseThrow最初の要素が見つからない場合は例外をスローできます

firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);

System.out.println(fisrstString);

[〜#〜] if [〜#〜]Optionalが空にならないことがわかっている場合は、_@SuppressWarnings_を使用できます以下のような注釈:

_@SuppressWarnings("ConstantConditions") String foo = Optional.of("bar").get();
_

時々_Optional.get_はNullPointerExceptionを発生させます。例:

_Optional<String> it = Optional.empty();
String foo = it.get();
          //   ^--- throws NullPointerException when this method is invoked
_

[〜#〜] so [〜#〜]この式を使用すると、Intellijはwarninging検査。

[〜#〜] if [〜#〜]すべての契約検査を無効にするには、次のアクションを実行できます。Settings->Inspections->Constant condition&exceptions オプション->設定を保存するために、下にあるApplyボタンをクリックすることを忘れないでください。

[〜#〜] if [〜#〜]Optional.get()警告以外のすべての契約検査を無効にしたくない次のアクションを実行します:Settings->Inspections->一定の条件と例外オプション->右下にOptional.get()警告を設定するフレームがあります->忘れないでください設定を保存するには、下部のApplyボタンをクリックします。

enter image description here

2
holi-java