将双嵌套for循环重写为Java 8流

时间:2018-10-25 01:16:19

标签: java java-8 java-stream

我有以下Java方法:

public List<GrantedAuthority> toAuthorities(Set<Role> roles) {
    List<GrantedAuthority> authorities = new ArrayList<>();

    if (null != roles) {
        for (Role role : roles) {
            for (Permission permission : role.getPermissions()) {
                authorities.add(new SimpleGrantedAuthority("ROLE_" + permission.getLabel()));
            }
        }
    }

    return authorities;
}

我正在尝试使用Java 8流重写它。迄今为止我最大的尝试:

public List<GrantedAuthority> toAuthorities(Set<Role> roles) {
    List<GrantedAuthority> authorities = new ArrayList<>();

    if (null != roles) {
        roles.stream().filter(role -> ???).collect(Collectors.toList());
    }

    return authorities;
}

但是我对流过滤器中的内容(替换为???)感到迷茫……有什么想法吗?

2 个答案:

答案 0 :(得分:4)

您可以使用flatMapmap instaead来做到这一点:

if (null != roles) {
    authorities = roles.stream()
         .flatMap(role -> role.getPermissions().stream()) // Stream<Permission>
         .map(permission -> 
                 new SimpleGrantedAuthority("ROLE_" + permission.getLabel())) // Stream<SimpleGrantedAuthority>
         .collect(Collectors.toList());
}

for循环代码中,您不会基于条件过滤/进行任何迭代,也不会遍历整个列表,因此此处不需要filter


使用上述方法,您的完整方法可以写成:

public List<GrantedAuthority> toAuthorities(Set<Role> roles) {
    return roles == null ? new ArrayList<>() : roles.stream()
            .flatMap(role -> role.getPermissions().stream())
            .map(permission -> new SimpleGrantedAuthority("ROLE_" + permission.getLabel()))
            .collect(Collectors.toList());
}

或者作为suggested by shmosel,使用方法引用,可以将其转换为:

return roles == null ? new ArrayList<>() : roles.stream()
        .map(Role::getPermissions)
        .flatMap(Collection::stream)
        .map(Permission::getLabel)
        .map("ROLE_"::concat)
        .map(SimpleGrantedAuthority::new)
        .collect(Collectors.toList());

答案 1 :(得分:2)

您可以在一个链中完成此操作,尽管不确定您的可读性:

public static List<GrantedAuthority> toAuthorities(Set<Role> roles) {
    return Optional.ofNullable(roles)
            .orElse(Collections.emptySet())
            .stream()
            .flatMap(r -> r.getPermissions().stream())
            .map(Permission::getLabel)
            .map("ROLE_"::concat)
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toList());
}