如何从可空对象中最好地创建Java 8流?

che*_*tts 29 java java-8 java-stream

在获取流之前进行空检查的最佳/惯用方法是什么?

我有接收List可能为null的方法.所以我不能只调用.stream()传入的值.是否有一些静态助手,如果值为null,会给我一个空流?

gde*_*ohn 47

我同意Stuart Markslist == null ? Stream.empty() : list.stream()是做到这一点的最佳方式(参见他的回答),或者至少是在Java 9之前做到这一点的最佳方式(见下面的编辑),但我会留下这个答案来证明可选API.

<T> Stream<T> getStream(List<T> list) {
    return Optional.ofNullable(list).map(List::stream).orElseGet(Stream::empty);
}
Run Code Online (Sandbox Code Playgroud)

编辑: Java 9添加了静态方法Stream.<T>ofNullable(T),它返回给定null参数的空流,否则返回一个以参数为唯一元素的流.如果参数是集合,我们可以flatMap将其转换为流.

<T> Stream<T> fromNullableCollection(Collection<? extends T> collection) {
    return Stream.ofNullable(collection).flatMap(Collection::stream);
}
Run Code Online (Sandbox Code Playgroud)

这并没有像Stuart Marks所讨论的那样滥用Optional API,与三元运算符解决方案相反,没有机会获得空指针异常(比如你没有注意并搞砸了操作数的顺序).它也适用于上限通配符而不需要SuppressWarnings("unchecked")感谢签名flatMap,因此您可以Stream<T>从任何子类型的元素集合中获取T.

  • `List :: stream`中不需要显式类型参数`<T>`; 没有.并且`.orElse(Stream.empty())`可以用`.orElseGet(Stream :: empty)`代替,它稍微有点效率,因为它避免构造一个空流. (3认同)
  • 请参阅["如何编译Java lambda函数?"](http://stackoverflow.com/q/16827262/2711488)和["每次执行时,lambda表达式是否在堆上创建对象?"](http ://stackoverflow.com/q/27524445/2711488).实际上,会有一个匿名类的实例,但它在每次执行代码时都是相同的实例(而`Stream.empty()`每次都返回一个新实例). (3认同)

che*_*tts 15

我能想到的最好的办法是使用一个OptionalorElseGet方法.

return Optional.ofNullable(userList)
                .orElseGet(Collections::emptyList)
                .stream()
                .map(user -> user.getName())
                .collect(toList());
Run Code Online (Sandbox Code Playgroud)

更新与@ Misha的建议使用Collections::emptyListArrayList::new

  • 最好使用`Collections :: emptyList`而不是`ArrayList :: new`.它使意图更加清晰,并且(略微)更高效. (4认同)

Stu*_*rks 13

在其他答案中,Optional实例是在同一语句中创建和使用的.的Optional类是主要有用与呼叫者通信约一个返回值的存在或不存在,以及如果存在的实际值熔合.完全在单一方法中使用它似乎是不必要的.

让我提出以下更平凡的技巧:

static <T> Stream<T> nullableListToStream(List<T> list) {
    return list == null ? Stream.empty() : list.stream();
}
Run Code Online (Sandbox Code Playgroud)

我想这三天的三元运算符有点多了,但我认为这是最简单,最有效的解决方案.

如果我是真的写这个(也就是说,对于一个真正的库,而不仅仅是Stack Overflow上的示例代码)我会添加通配符,以便流返回类型可以与List类型不同.哦,它可以是一个集合,因为这stream()是定义方法的地方:

@SuppressWarnings("unchecked")
static <T> Stream<T> nullableCollectionToStream(Collection<? extends T> coll) {
    return coll == null ? Stream.empty() : (Stream<T>)coll.stream();
}
Run Code Online (Sandbox Code Playgroud)

(警告抑制是必要的,因为从演员Stream<? extends T>Stream<T>它是安全的,但是编译器不知道.)


Mic*_*ksa 12

Java 8:

Optional.ofNullable(list)
   .orElseGet(Collections::emptyList)
   .stream()
Run Code Online (Sandbox Code Playgroud)

Java 9:

Stream.ofNullable(collection)
    .flatMap(Collection::stream)
Run Code Online (Sandbox Code Playgroud)

Apache Commons Collections 4:

import org.apache.commons.collections4.CollectionUtils;

CollectionUtils.emptyIfNull(collection)
    .stream()
Run Code Online (Sandbox Code Playgroud)


pio*_*rek 6

apache commons-collections4:

CollectionUtils.emptyIfNull(list).stream()
Run Code Online (Sandbox Code Playgroud)