首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8流通过多个层,并将最底层的所有项连接起来。

Java 8流通过多个层,并将最底层的所有项连接起来。
EN

Stack Overflow用户
提问于 2017-09-07 16:53:25
回答 4查看 1.5K关注 0票数 4

我目前有一个多层结构数据,如下所示:

行业类有一个可以为空的私有字段Set<Company>。 Company类有一个可以为空的私有字段Set<Division>。 除法类有一个可以为空的私有字段Set<Group>。 Group类有一个私有字段groupName,该字段可以为null,可以使用getter (getGroupName())检索。

我试图将Industry的一个实例源源不断地流到Group层,并将所有groupName连接到一个字符串中,中间有"/“。

如果此工业实例不包含任何groupName,则返回字符串"null“。

基于我对Java 8的有限知识,我想编写如下代码:

代码语言:javascript
复制
industry.stream()
     .flatmap(industry -> industry.getCompanies().stream())
     .filter(Objects::nonNull)
     .flatmap(company -> company.getDivisions().stream())
     .filter(Objects::nonNull)
     .flatmap(division -> division.getGroups().stream())
     .map(group -> group.getGroupName)
     .collect(Collectors.joining("/")));

这段代码在某些方面似乎有缺陷。另外,我不知道该在哪里添加这样的语句:如果工业无法检索任何groupName,而不是将所有groupName连接到一个字符串中,只需返回一个字符串"null“。

在我的情况下,使用Java 8流的正确方法是什么?

谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-09-07 17:09:49

Collectors.joining(…)是基于类StringJoiner的。它提供了它的分隔符、前缀和后缀功能,但不幸的是它没有提供空值的能力。

要添加这个特性,我们必须重新实现Collectors.joining,谢天谢地,使用StringJoiner并不难。

更改流操作的最后一行

代码语言:javascript
复制
.collect(Collectors.joining("/"));

代码语言:javascript
复制
.filter(Objects::nonNull) // elide all null elements
.collect(()->new StringJoiner("/", "", "").setEmptyValue("null"), // use "null" when empty
         StringJoiner::add, StringJoiner::merge).toString();
票数 8
EN

Stack Overflow用户

发布于 2017-09-07 17:35:14

我很理解你的问题,几乎任何事情都是无效的。在这种情况下,您可以创建自己的函数来处理这个问题。我做了一个这样的:

代码语言:javascript
复制
/**
 * Creates a stream function for the provided collection function which ignores all null values.
 * Will filter out null values passed into the collection function and null values from the resulting stream
 * @param collectionFn
 * @param <T>
 * @param <R>
 * @return
 */
public static <T, R> Function<T, Stream<R>> nullSafeMapper(Function<T, Collection<R>> collectionFn) {
    return (v) -> Optional.ofNullable(v)
            .map(collectionFn)
            .map(Collection::stream)
            .orElse(Stream.empty())
            .filter(Objects::nonNull);
}

基本上它是完全空安全的,过滤掉输入和输出中的空值。并可作为下列用途:

代码语言:javascript
复制
industries.stream()
    .flatMap(SO46101593.nullSafeMapper(Industry::getCompanies))
    .flatMap(SO46101593.nullSafeMapper(Company::getDivisions))
    .flatMap(SO46101593.nullSafeMapper(Division::getGroups))
    .map(group -> group.getGroupName())
    .filter(Objects::nonNull) // filter out null group names
    .collect(Collectors.joining("/"));

你也可以把这个逻辑直接推到你的表达式中,但是由于它必须重复3次,所以它会变得有点.冗长重复

票数 0
EN

Stack Overflow用户

发布于 2017-09-07 17:36:27

下面是一个带有空检查的示例:

代码语言:javascript
复制
String s = industries.stream()
.filter( i -> i.getCompanies() != null ).flatMap( i -> i.getCompanies().stream() )
    .filter( c -> c != null && c.getDivisions() != null ).flatMap( c -> c.getDivisions().stream() )
        .filter( d -> d != null && d.getGroups() != null ).flatMap( d -> d.getGroups().stream() )
            .filter( g -> g != null && g.getGroupName() != null ).map( g -> g.getGroupName() )                    
.collect( Collectors.joining("/") );   

您可以将Collectors.joining("/")替换为Holger的示例。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46101593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档