'How to fill in a property in a collection with help of stream operators? [closed]

I have two lists of objects builders of type Builder and adminUsers of type AdminUser.

Here are type defenitions of the classes:

public class Builder {
    @Id
    private String id;
    private String name;
    @Field("company_name")
    private String companyName;
    @Indexed(unique=true)
    private String email;
    private UserRole userRole;
}

public class AdminUser {
    @Id
    private String id;
    @Indexed(unique=true)
    private String email;
    private List<GrantedAuthority> authorities;
}

public enum UserRole {
    ROLE_ADMIN,
    ROLE_DATA,
    ROLE_BUILDER
}

I try to fill property which is called UserRole of the builders collection with a UserRole property from adminUser collection of each item in builders collection.

Here is how I am doing it in imperative attitude:

List<Builder> builders = builderRepository.findAllBy();
List<AdminUser> adminUsers = adminUserRepository.findAllBy();

for (Builder builder : builders) {
    for (AdminUser adminUser : adminUsers) {

        if (builder.getEmail().equals(adminUser.getEmail()))
            builder.setUserRole(UserRole.valueOf(adminUser.getAuthorities().get(0).getAuthority()));
    }
}

The code above works.

I tried to achieve the same with a declarative attitude with streams operators. But I got confused and ended up writing it the good old imperative way. Could you help me and show me an example of how the code above can be written with help of streams and intermediate operators, in a declarative way?



Solution 1:[1]

Streams can be used for filtering, transformation, or some other operation. Generally, one or more collections are converted to other collections, or the size of a collection is changed. However, in your example, there is no collection conversion or size change. At most, replace the for loop in your example with forEach, but it doesn't make sense.

When the number of Builders and AdminUsers is large, the complexity of this code is O(n^2). You can use hash to reduce complexity.

Map<String, String> emailAuthMap = adminUsers.stream()
                .collect(Collectors.toMap(AdminUser::getEmail, u -> u.getAuthorities().size() > 0 ? u.getAuthorities().get(0).getAuthority() : null));
for (Builder builder : builders) {
    String auth = emailAuthMap.get(builder.getUserRole());
    builder.setUserRole(auth != null ? UserRole.valueOf(auth) : null);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1