Rewrite double nested for loop as a Java 8 stream

匆匆过客 提交于 2020-12-29 12:20:29

问题


I have the following Java method:

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;
}

I'm trying to rewrite it using Java 8 streams. My best attempt thus far:

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

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

    return authorities;
}

But I'm at a loss as to what I put in the stream filter (substituting ???)...any ideas?


回答1:


You can do it using flatMap and map instaead as :

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());
}

In the for loop code, you are not filtering out/in any iteration based on a condition and iterating throughout the lists, hence you don't require a filter here.


And using the above your complete method could be written as :

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());
}

Or as suggested by shmosel, with method references this could be transformed as :

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());



回答2:


You could do it in a single chain, not sure how readable that is to you though:

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());
}


来源:https://stackoverflow.com/questions/52979975/rewrite-double-nested-for-loop-as-a-java-8-stream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!