web-dev-qa-db-ja.com

Java8でラムダを使用してnullでない場合にのみ値をフィルタリングする

carname__というオブジェクトのリストがあります。 Java 8を使用して、このリストを何らかのパラメーターに基づいてフィルタリングしたいのですが、パラメーターがnullname__の場合、NullPointerExceptionname__がスローされます。 null値を除外する方法

現在のコードは以下の通りです

requiredCars = cars.stream().filter(c -> c.getName().startsWith("M"));

getName()NullPointerExceptionname__を返す場合、これはnullname__をスローします。

123
vaibhavvc1092

この特定の例では、私は@Tagirが100%正しいと考えています。それを1つのフィルターに入れて2つのチェックを行います。私はOptional.ofNullableを使いたくはありませんが、Optional型は実際には戻り型がロジックを実行しないようにするためのものです...しかし実際にはここでもそこでもありません。

私はJava.util.Objectsがこの場合にはいい方法を持っていることを広い範囲で指摘したかったので、あなたはこれをすることができます:

cars.stream()
    .filter(Objects::nonNull)

これはあなたのnullオブジェクトを消去します。なじみのない人にとっては、それは以下の略語です。

cars.stream()
    .filter(car -> Objects.nonNull(car))

手元の質問に部分的に答えて、"M"で始まる車の名前のリストを返すには、次のようにします。

cars.stream()
    .filter(car -> Objects.nonNull(car))
    .map(car -> car.getName())
    .filter(carName -> Objects.nonNull(carName))
    .filter(carName -> carName.startsWith("M"))
    .collect(Collectors.toList());

省略形のラムダに慣れたら、次のようにすることもできます。

cars.stream()
    .filter(Objects::nonNull)
    .map(Car::getName)        // Assume the class name for car is Car
    .filter(Objects::nonNull)
    .filter(carName -> carName.startsWith("M"))
    .collect(Collectors.toList());

残念ながら、一度あなたが.map(Car::getName)すると、あなたは車ではなく名前のリストを返すだけです。それほど美しくありませんが、完全に質問に答えます:

cars.stream()
    .filter(car -> Objects.nonNull(car))
    .filter(car -> Objects.nonNull(car.getName()))
    .filter(car -> car.getName().startsWith("M"))
    .collect(Collectors.toList());
264
xbakesx

あなたはnullという名前を持つ車をフィルタリングする必要があります。

requiredCars = cars.stream()
                   .filter(c -> c.getName() != null)
                   .filter(c -> c.getName().startsWith("M"));
44
Tunaki

提案された答えは素晴らしいです。 Optional.ofNullableを使用してnullリストのケースを処理するための改善を提案したいだけです、 Java 8の新機能

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

したがって、完全な答えは次のようになります。

 List<String> carsFiltered = Optional.ofNullable(cars)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull) //filtering car object that are null
                .map(Car::getName) //now it's a stream of Strings
                .filter(Objects::nonNull) //filtering null in Strings
                .filter(name -> name.startsWith("M"))
                .collect(Collectors.toList()); //back to List of Strings
35
Stas

これは単一のフィルタステップで実行できます。

requiredCars = cars.stream().filter(c -> c.getName() != null && c.getName().startsWith("M"));

getName()を何度も呼び出したくない場合(たとえば、高額な呼び出し)、これを実行できます。

requiredCars = cars.stream().filter(c -> {
    String name = c.getName();
    return name != null && name.startsWith("M");
});

またはもっと洗練された方法で:

requiredCars = cars.stream().filter(c -> 
    Optional.ofNullable(c.getName()).filter(name -> name.startsWith("M")).isPresent());
19
Tagir Valeev

これを使用できます

List<Car> requiredCars = cars.stream()
    .filter (t->  t!= null && StringUtils.startsWith(t.getName(),"M"))
    .collect(Collectors.toList());

1
riverfan