java 处理空对象并在流中抛出异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31334326/
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-11-02 18:27:13  来源:igfitidea点击:

Handling null objects and throwing exceptions in streams

javalambdajava-8

提问by Manu Joy

Let's consider a Parentclass which contains only one Integerattribute. I created 6 objects of parent class and with one object as null. Then I added these objects to a list.

让我们考虑一个Parent只包含一个Integer属性的类。我创建了 6 个父类对象,其中一个对象为 null。然后我将这些对象添加到列表中。

I want to retrieve the corresponding object by the value of Integerattribute. I used Java 8 Streams for it.

我想通过Integer属性的值来检索相应的对象。我为此使用了 Java 8 Streams。

Predicate<Parent> predicate = e -> e.getId() == 100; // sample attribute value
result = list.stream().filter(predicate).collect(Collectors.toList());

But I got NullPointerException, so I edited the code:

但是我得到了NullPointerException,所以我编辑了代码:

list.stream().filter(h -> h!=null).filter(predicate).collect(Collectors.toList());

But I want to throw an exception if any of the object is null. If no objects in the list is null, then I want to retrieve the corresponding object from list.

但如果任何对象为空,我想抛出异常。如果列表中没有对象为空,那么我想从列表中检索相应的对象。

How can I achieve this using a single statement using Java 8 Streams?

如何使用 Java 8 Streams 使用单个语句实现此目的?

回答by Lii

JB Nizet answer is okay, but it uses maponly for its side effects and not for the mapping operation, which is kind of weird. There is a method which can be used when you are solely interested in the side effects of something, such as throwing an exception: peek.

JB Nizet 的答案是可以的,但它map仅用于其副作用,而不用于映射操作,这有点奇怪。有可以当你的东西的副作用,如引发异常的兴趣完全可以使用的方法:peek

List<Parent> filtered = 
    list.stream()
        .peek(Objects::requireNonNull)
        .filter(predicate)
        .collect(Collectors.toList());

And if you want your own exception just put a lambda in there:

如果您想要自己的异常,只需在其中放置一个 lambda:

List<Parent> filtered = 
    list.stream()
        .peek(p -> { if (p == null) throw new MyException(); })
        .filter(predicate)
        .collect(Collectors.toList());


Checked Exceptions

检查异常

If your exception is checked you can either check for null beforehand, if you don't mind traversing the list twice. This is probably best in your case, but might not always be possible.

如果您的异常被检查,您可以事先检查空值,如果您不介意遍历列表两次。这对您来说可能是最好的,但可能并不总是可行的。

if (list.contains(null)) throw new MyCheckedException();

You could also throw an unchecked exception in your stream pipeline, catch it and then throw the checked one:

你也可以在你的流管道中抛出一个未经检查的异常,捕捉它然后抛出已检查的异常:

try {
    ...
        .peek(p -> { if (p == null) throw new MyException(); })
    ...
} catch (MyException exc) {
    throw new MyCheckedException();
}


Sneaky Throw

偷偷投掷

Or you could take the elegant but controversial road and use a sneaky throw method.

或者你可以走优雅但有争议的道路,使用偷偷摸摸的方法

But beware!This technique circumvents the checked exception system and you should know what you are doing. Be sure to declare that the surrounding method throws MyCheckedException! The compiler won't warn you if you don't, and it will likely cause weird bugs if checked exceptions appear where they are not expected.

但要小心!这种技术绕过了检查异常系统,你应该知道你在做什么。一定要声明周围的方法 throws MyCheckedException!如果您不这样做,编译器将不会警告您,并且如果检查异常出现在不期望的地方,它可能会导致奇怪的错误。

@SuppressWarnings("unchecked")
public <T extends Throwable> void throwSneakily(Throwable t) throws T {
    throw (T) t;
}

public void m() throws MyCheckedException {
    List<Parent> filtered = 
        list.stream()
            .peek(p -> { if (p == null) throwSneakily(new MyCheckedException()); })
            .filter(predicate)
            .collect(Collectors.toList());
}

回答by Holger

Let's start with the simplest solution:

让我们从最简单的解决方案开始:

if(list.contains(null)) throw new MyException();
result = list.stream().filter(predicate).collect(Collectors.toList());

If you suspect the list to contain nulls and even have a specialized exception type to flag this condition, a pre-check is the cleanest solution. This ensures that such condition doesn't silently remain if the predicate changes to something that can handle nulls or when you use a short-circuiting stream operation that may end before encountering a subsequent null.

如果您怀疑列表包含nulls 并且甚至有专门的异常类型来标记这种情况,则预检查是最干净的解决方案。这可确保如果谓词更改为可以处理nulls 的内容,或者当您使用可能在遇到后续null.

If the occurrence of nullin the list still is considered a programming error that shouldn't happen, but you just want to change the exception type (I can't imagine a real reason for this), you may just catch and translate the exception:

如果null列表中的 出现仍然被认为是不应该发生的编程错误,但您只想更改异常类型(我无法想象真正的原因),您可以捕获并转换异常:

try {
    result = list.stream().filter(predicate).collect(Collectors.toList());
}
catch(NullPointerException ex) {
    if(list.contains(null)) // ensure that we don't hide another programming error
        throw new MyException();
    else throw ex;
}

This works efficient under the assumption that nullreferences do notoccur. As said, if you suspect the list to contain nullyou should prefer a pre-check.

这在发生null引用的假设下有效。如上所述,如果您怀疑该列表包含您应该更喜欢预先检查。null

回答by JB Nizet

Function<Parent, Parent> throwingIdentity = p -> {
    if (p == null) {
        throw new MyException();
    }
    return p;
};

List<Parent> filtered = 
    list.stream()
        .map(throwingIdentity)
        .filter(predicate)
        .collect(Collectors.toList());