仅当在 Java8 中使用 lambda 不为 null 时才过滤值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32884195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:58:55  来源:igfitidea点击:

Filter values only if not null using lambda in Java8

javalambdanullpointerexceptionnulljava-8

提问by vaibhavvc1092

I have a list of objects say car. I want to filter this list based on some parameter using Java 8. But if the parameter is null, it throws NullPointerException. How to filter out null values?

我有一个对象列表说car。我想使用 Java 8 根据某个参数过滤此列表。但如果参数是null,它会抛出NullPointerException. 如何过滤掉空值?

Current code is as follows

当前代码如下

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

This throws NullPointerExceptionif getName()returns null.

这将抛出NullPointerExceptionifgetName()返回null

回答by Tunaki

You just need to filter the cars that have a nullname:

您只需要过滤具有null名称的汽车:

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

回答by Tagir Valeev

You can do this in single filter step:

您可以在单个过滤步骤中执行此操作:

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

If you don't want to call getName()several times (for example, it's expensive call), you can do this:

如果您不想getName()多次调用(例如,这是昂贵的调用),您可以这样做:

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

Or in more sophisticated way:

或者以更复杂的方式:

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

回答by xbakesx

In this particular example I think @Tagir is 100% correct get it into one filter and do the two checks. I wouldn't use Optional.ofNullablethe Optional stuff is really for return types not to be doing logic... but really neither here nor there.

在这个特定的例子中,我认为 @Tagir 是 100% 正确的,将它放入一个过滤器并进行两项检查。我不会使用Optional.ofNullableOptional 的东西真的是为了返回类型不做逻辑......但实际上既不在这里也不在那里。

I wanted to point out that java.util.Objectshas a nice method for this in a broad case, so you can do this:

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

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

Which will clear out your null objects. For anyone not familiar, that's the short-hand for the following:

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

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

To partially answer the question at hand to return the list of car names that starts with "M":

部分回答手头的问题以返回以 开头的汽车名称列表"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());

Once you get used to the shorthand lambdas you could also do this:

一旦你习惯了简写 lambdas,你也可以这样做:

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

Unfortunately once you .map(Car::getName)you'll only be returning the list of names, not the cars. So less beautiful but fully answers the question:

不幸的是,一旦你.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());

回答by Johnny

The proposed answers are great. Just would like to suggest an improvement to handle the case of null list using Optional.ofNullable, new feature in Java 8:

建议的答案很棒。只是想提出一个改进使用处理空单的情况下Optional.ofNullable用Java 8新特性

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

So, the full answer will be:

所以,完整的答案将是:

 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

回答by riverfan

you can use this

你可以用这个

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

回答by rslemos

Leveraging the power of java.util.Optional#map():

利用以下力量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())
;