仅在 Java8 中使用 lambda 过滤不为 null 的值

问题描述 投票:0回答:7

我有一个对象列表,上面写着

car
。我想使用 Java 8 根据某些参数过滤此列表。但是如果参数是
null
,则会抛出
NullPointerException
。如何过滤掉空值?

当前代码如下

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

如果

NullPointerException
返回
getName()
,则会抛出
null

java lambda nullpointerexception null java-8
7个回答
520
投票

在这个特定的例子中,我认为@Tagir 100%正确地将其放入一个过滤器中并进行两项检查。我不会使用

Optional.ofNullable
可选的东西实际上是为了返回类型而不是做逻辑......但实际上既不在这里也不在那里。

我想指出,

java.util.Objects
在广泛的情况下有一个很好的方法,所以你可以这样做:

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

这将清除您的空对象。对于不熟悉的人,这是以下内容的简写:

    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());

一旦您习惯了简写 lambda,您也可以这样做:

    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());

91
投票

您只需过滤具有

null
名称的汽车:

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

68
投票

建议的答案很棒。只是想建议改进使用

null
处理
Optional.ofNullable
列表的情况,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

32
投票

您可以在单个过滤步骤中完成此操作:

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());

4
投票

你可以用这个

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


4
投票

利用

java.util.Optional#map()
的力量:

List<Car> requiredCars = cars.stream()
  .filter (car -> 
    Optional.ofNullable(car)
      .map(Car::getName)
      .map(name -> name.startsWith("M"))
      .orElse(false) // what to do if either car or getName() yields null? false will filter out the element
    )
  .collect(Collectors.toList())
;

0
投票

您可以应用Objects.nonNull,或者您可以对过滤器内的汽车对象进行空检查,并在同一过滤器方法中应用其他条件。

List<Car> list = carsList.stream()
         .filter(c-> Objects.nonNull(c) && c.getName().startWith("M"))
         .collect(Collectors.toList());

© www.soinside.com 2019 - 2024. All rights reserved.