繁体   English   中英

Java 8流API或Else用法

[英]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来进行此操作。

注意:上述解决方案确实假设emptyMapCollections.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返回一个Optionaluser -> user.getData().orElse(emptyMap())

方法3:

正如@Eran所说: Optional.ofNullable然后像上面一样使用orElse(emptyMap())user -> Optional.ofNullable(user.getData()).orElse(emptyMap())

为什么我不能在这种情况下使用orElse?

不知道orElse你的意思

  1. 如果user.getData()返回null ,则应将其包装为Optional以调用orElse

  2. 流的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::mapjava.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM