97

in advanceJDK8 はまだリリースされていないため (とにかく今のところはそうではありません..)、この件名は少し難しいかもしれませんが、Lambda 式に関するいくつかの記事、特に Stream として知られる新しいコレクション API に関連する部分を読んでいました。

以下は、Java Magazine の記事に記載されている例です (これはカワウソ個体群アルゴリズムです..):

Set<Otter> otters = getOtters();
System.out.println(otters.stream()
    .filter(o -> !o.isWild())
    .map(o -> o.getKeeper())
    .filter(k -> k.isFemale())
    .into(new ArrayList<>())
    .size());

私の質問は、セットの内部反復の途中で、カワウソの 1 つが null の場合はどうなるかということです。

NullPointerException がスローされることを期待しますが、以前の開発パラダイム (非機能) にまだとどまっている可能性があります。

これが実際に NullPointerException をスローする場合、この機能は非常に危険であることがわかり、以下のようにのみ使用する必要があります。

  • null 値がないことを確認する開発者 (おそらく以前の .filter(o -> o != null) を使用)
  • 開発者は、アプリケーションが null otter または処理する特別な NullOtter オブジェクトを生成しないようにします。

最良の選択肢、または他の選択肢は何ですか?

4

5 に答える 5

115

答えは 100% 正しいですが、 Optionalnullを使用してリスト自体のケース処理を改善するための小さな提案:

 List<String> listOfStuffFiltered = Optional.ofNullable(listOfStuff)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

この部分Optional.ofNullable(listOfStuff).orElseGet(Collections::emptyList)を使用すると、nullPointerException で失敗する代わりに、null の場合をlistOfStuff適切に処理して emptyList を返すことができます。

于 2016-08-29T14:58:07.283 に答える
45

現在の考え方は、null を「許容」すること、つまり、一般的に許可することですが、一部の操作は許容範囲が狭く、最終的に NPE をスローする可能性があります。Lambda ライブラリのエキスパート グループのメーリング リストで null に関する議論、特にこのメッセージを参照してください。その後、オプション #3 に関するコンセンサスが得られました (Doug Lea からの注目すべき反対意見もありました)。そうです、パイプラインがNPEで爆発するというOPの懸念は有効です。

Tony Hoare が null を「10 億ドルの間違い」と呼んだのは、当然のことです。null を扱うのは本当に苦痛です。従来のコレクション (ラムダやストリームを考慮しない) でも、null には問題があります。コメントでfgeが述べたように、 nullを許可するコレクションと許可しないコレクションがあります。null を許可するコレクションでは、API にあいまいさが生じます。たとえば、Map.get()では、null の戻り値は、キーが存在し、その値が null であること、またはキーが存在しないことを示します。これらのケースを明確にするために、追加の作業を行う必要があります。

null の通常の使用法は、値がないことを示すことです。Java SE 8 で提案されているこれに対処するためのアプローチはjava.util.Optional、デフォルト値の提供、例外のスロー、関数の呼び出しなどの動作とともに、値の存在/不在をカプセル化する新しい型を導入することです。値がありません。Optionalは新しい API でのみ使用されますが、システム内の他のすべての機能は、null の可能性を許容する必要があります。

私のアドバイスは、可能な限り実際の null 参照を避けることです。「null」の Otter がどのように存在する可能性があるかを考えると、この例からはわかりにくいです。ただし、必要な場合は、null 値を除外するか、それらをセンチネル オブジェクト ( Null Object Pattern ) にマッピングするという OP の提案が優れたアプローチです。

于 2013-06-14T18:59:21.423 に答える
19

null 値をストリームから除外するだけの場合は、単にjava.util.Objects.nonNull(Object)へのメソッド参照を使用できます。そのドキュメントから:

このメソッドは、Predicateとして使用するために存在します。filter(Objects::nonNull)

例えば:

List<String> list = Arrays.asList( null, "Foo", null, "Bar", null, null);

list.stream()
    .filter( Objects::nonNull )  // <-- Filter out null values
    .forEach( System.out::println );

これは印刷されます:

Foo
Bar
于 2016-03-04T19:48:51.787 に答える
7

null を回避する方法の例 (例: groupingBy の前にフィルターを使用)

groupingBy の前に null インスタンスを除外します。

ここに例があります

MyObjectlist.stream()
            .filter(p -> p.getSomeInstance() != null)
            .collect(Collectors.groupingBy(MyObject::getSomeInstance));
于 2015-08-25T15:23:58.593 に答える