[英]Java 8 stream API orElse usage
我要做的是过滤列表,然后映射它并使用orElse
如果为null
,然后将其收集回列表。 现在我可以通过这种方式实现它:
return users.stream()
.filter(user -> id.equals(user.getId()))
.map(
user -> {
if(user.getData() != null) {
return user.getData();
}
return Collections.emptyMap();
}
)
.collect(Collectors.toList());
但问题是:我怎样才能使这个结构更好,为什么我orElse
在这种情况下使用orElse
?
使用三元条件运算符可能更具可读性:
return users.stream()
.filter(user -> id.equals(user.getId()))
.map(
user -> (user.getData() != null)
? user.getData()
: emptyMap()
)
.collect(Collectors.toList())
;
为了使用orElse
你必须创建一个包装user.getData()
的Optional
。 我不确定这是个好主意。
如果你坚持使用orElse
(或者甚至更好,或者是orElseGet
,以避免在不需要时评估emptyMap()
),它可能如下所示:
return users.stream()
.filter(user -> id.equals(user.getId()))
.map(
user -> Optional.ofNullable(
user.getData()
).orElseGet(
() -> emptyMap()
)
)
.collect(Collectors.toList())
;
正如我在评论中指出的那样,我非常怀疑你可能只是在寻找以下内容
users
.stream()
.filter(
user -> id.equals(user.getId())
&& (user.getData() != null)
)
.map(User::getData)
.collect(Collectors.toList())
;
但是问题还不清楚,你的语句的最终返回类型是什么, emptyMap
代码中使用的emptyMap
是什么! 因此,我非常怀疑,如果您甚至首先需要一个Optional
API来进行此操作。
注意:上述解决方案确实假设emptyMap
是Collections.emptyMap
,我不确定为什么要在表示为List<Map<K,V>>
的数据结构中收集。
我怎样才能使这个结构更好
方法1:
return users.stream()
.filter(user -> id.equals(user.getId()))
.map(
user -> (user.getData() != null)
? user.getData()
: emptyMap()
)
.collect(Collectors.toList())
;
方法2:
让你的getData
返回一个Optional
: user -> user.getData().orElse(emptyMap())
方法3:
正如@Eran所说: Optional.ofNullable
然后像上面一样使用orElse(emptyMap())
: user -> Optional.ofNullable(user.getData()).orElse(emptyMap())
为什么我不能在这种情况下使用orElse?
不知道orElse
你的意思
如果user.getData()
返回null
,则应将其包装为Optional
以调用orElse
。
流的findAny().orElse
对流的结果本身进行操作。 但是你需要的是检查user.getData()
存在。 所以你不能直接使用stream的结果orElse
。
Objects::requireNonNullElse
! 我会建议两件事让代码更具可读性。 但是,我不会人为地介绍一个Optional
。
Objects::requireNonNullElse
在一个单独的方法中 List<Map<?, ?> bar() {
//...
return users.stream()
.filter(user -> id.equals(user.getId()))
.map(User::getData)
.map(Foo::nullSafeMap)
.collect(Collectors.toList());
}
private static Map<?, ?> nullSafeMap(final Map<?, ?> map) {
return Objects.requireNonNullElse(map, Collections.emptyMap());
}
在这里,您将使用Objects::requireNonNullElse
,如果第一个参数不为null
,则返回在第一个参数中传递的对象;如果第一个参数为null
,则返回作为第二个参数传递的对象。 使用单独的方法允许将方法引用传递给Stream::map
,但需要首先将User
实例映射到其数据Map
。
Objects::requireNonNullElse
List<Map<?, ?> bar() {
//...
return users.stream()
.filter(user -> id.equals(user.getId()))
.map(User::getData)
.map(map -> Objects.requireNonNullElse(map, Collections.emptyMap()))
.collect(Collectors.toList());
}
如果您不希望单独的方法只执行此单个任务,则可以内联该方法,并可选择删除第一个映射,转而使用.map(user -> Objects.requireNonNullElse(user.getData(), Collections.emptyMap()))
,但我会建议不要这样做。 如果它使代码更具可读性,请不要害怕对Stream::map
进行多次调用。
我更喜欢第一个选项,因为它使代码非常易读:您知道将User
实例映射到数据,然后您将该数据保持为null。
第二种选择没问题,但是很长的路线可能会让人感到困惑。 它比拥有多线lambda要好得多。 我会不惜一切代价避免使用多行lambda,并始终将其内容提取到一个单独的方法中。
您可以改进的一件事是方法名称nullSafeMap
,以避免Stream::map
和java.util.Map
之间的混淆。
请注意,您不需要使用Objects::requireNonNullElseGet
因为Collections::emptyMap
是一个轻量级方法,只能转换并返回一个常量:
public static final <K,V> Map<K,V> emptyMap() {
return (Map<K,V>) EMPTY_MAP;
}
Objects::requireNonNullElseGet
用于检索或创建重量级的默认对象。
如果您已将Apache Collections 4作为依赖项:
return users
.stream()
.filter(user -> id.equals(user.getId()))
.map(User::getData)
.map(MapUtils::emptyIfNull)
.collect(Collectors.toList())
;
如果您不使用Apache Collections,只需定义一个帮助方法:
public static <K,V> Map<K,V> emptyIfNull(Map<K,V> map) {
return map == null ? Collections.<K,V>emptyMap() : map;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.