I have the following 2 objects Team
and Group
. I have standard getters setters and toString methods in each of these classes and not allowed to modify them.
public class Team {
private List<Team> teams;
private List<TeamMember> members;
private String teamId;
}
public class Group {
private List<GroupMember> groupMember;
private List<Group> groups;
private String groupId;
}
Team can have a List<Team>
type of a list as an attribute where List<Group>
can have a List<Group>
as an attribute.
example list of Teams look like follows:
I want to create the list of Groups which reflects the same structure of TeamList
.
This is what I have got so far.
@Service
public class GroupService {
@Autowired
TeamService teamService;
public List<Group> createGroupList(){
List<Group> groups = Collections.emptyList();
List<Team> teams = teamService.createTeamList();
if (teams != null && !teams.isEmpty()) {
groups = teams.stream().map(t -> {
Group group = new Group();
group.setGroupId(t.getTeamId());
//this is to be modified
group.setGroups(getSubgroups(teams, group.getGroupId()));
return group;
}).collect(Collectors.toList());
}
return groups;
}
private List<Group> getSubgroups(List<Team> teams, String parentGroupName) {
Optional<Team> parentTeam = teams.stream()
.filter(t -> t.getTeamId().equalsIgnoreCase(parentGroupName)).findFirst();
if(parentTeam.isPresent()){
List<Team> subTeams = new ArrayList<>();
List<Group> lstOfGroups = new ArrayList<>();
System.out.println("parentname " + parentTeam.get().getTeamId());
if(parentTeam.get().getTeams() != null){
parentTeam.get().getTeams().stream().forEach(r -> {
subTeams.add(r);
});
}
subTeams.stream().forEach(st -> {
Group gr = new Group();
gr.setGroupId(st.getTeamId());
lstOfGroups.add(gr);
});
return lstOfGroups;
}
return null;
}
}
My idea is to modify the getSubgroups method to set the subgroups correctly for each given path.(eg: getSubgroubs can return team2 with all it's subgroups set until team7) I know I have to use recursion but I am struggling to find the solution. How can I achieve this?
EDIT
I have updated my code and now I can access the first level of children and not the other levels yet
You can just create a single method to copy one into the other and call it recursively:
public Group toGroup(Team team) {
Group result = new Group(team.teamId());
// this is missing in your sample code
result.setGroupMembers(transform(team.getTeamMembers());
List<Group> subGroups = team.getTeams().stream()
.map(this::toGroup) // recursive call to this method
.collect(toList());
result.setSubgroups(subGroups);
return result;
}
so you can do
List<Group> groups = teamService.getTeams()
// you should return an empty list if no elements are present
.stream()
.map(this::toGroup) // initial call
.collect(toList());
You might also want to look into mapstruct which can automatically generate simple mappers.
To give you an idea how this would look in mapstruct:
@Mapper(componentModel="spring")
interface TeamGroupMapper {
@Mappings({
@Mapping(source="teamId", target="groupId"),
@Mapping(source="teams", target="groups"),
@Mapping(source="teamMembers", target="groupMembers")
})
Group toGroup(Team team);
List<Group> toGroups(List<Team> teams);
GroupMember toGroupMember(TeamMember teamMember);
}
The actual code will be generated. If the classes have properties with the same name (eg if the ids were called id
for both Team
and Group?
), a @Mapping
annotation is not needed for it.
Then, you can @Autowire
this as a component and use it.
@Component
class YourGroupService implements GroupService {
@Autowired TeamGroupMapper mapper;
@Autowired TeamService teamService;
public List<Group> getGroups() {
return mapper.toGroups(teamService.getTeams());
}
}
I'm sure this code won't actually work, but it should give you an idea of what mapstruct does. I really like it to avoid boilerplate mapping code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.