javajava-stream

Java: How to stream a many-to-one list (with flatMap?)


I need to stream a many-to-one list. I believe I need a flatMap, but I can't get it going. I have the following objects:

UserRoles:

@Data
@AllArgsConstructor
public class UserRoles {
  private int userId;
  private Integer projectId;    
  private List<Integer> userRoles;
}

UserProjectRole:

public class UserProjectRole {    
  @EmbeddedId private UserProjectRolePk id;
  private User user;
  private Project project;
  private UserRole userRole;
}

Given a list of UserRoles, I need to create a list of new UserProjectRole. I have this so far:

List<UserProjectRole> projectRoles = userRolesDtos.stream()
             .map(it -> Stream.of(it.getUserRoles())
                     .flatMap(x -> new UserProjectRole(it.getUserId(), it.getProjectId(), x)))
             .collect(Collectors.toList());

But x is a List<Integer>, when I expected it to be just the roleId. Can anyone help?


Solution

  • Stream.of() creates a stream from a varargs array. As you pass a list, it creates a stream with one element which is a list.

    Try getting the stream from the list. Also flatMap() works an a stream result only (look on order and braces).

    List<UserProjectRole> projectRoles = userRolesDtos.stream()
        // stream of UserProjectRole
        .flatMap(it -> it.getUserRoles().stream()
            // intermediate stream of Integer
            .map(x -> new UserProjectRole(it.getUserId(), it.getProjectId(), x)
            // mapped to intermediate stream of UserProjectRole
        )
        // finished call to flatMap returning a flat stream of UserProjectRole
        .collect(Collectors.toList());