qul
qul

Reputation: 43

Get max value from nested lists and transform into one list using stream

League has 20 Team, team has 11 Player, player has int score field.

 class Player {
        private int score;

        public int getScore() {
            return score;
        }
    }

    class Team {
        private List<Player> players;

        public List<Player> getPlayers() {
            return players;
        }
    }

    class League {
        private List<Team> teams;

        public List<Team> getTeams() {
            return teams;
        }
    }

Need to select from List<Team> best Player with highest score and return one List<Player> including one best player from each team using Stream.

 public  List<Player> getTopPlayersFromEachTeam(List<Team> league) {
        // implementation
    }

Stuck at:

league.stream().map(Team::getPlayers).collect(Collectors.toList())

Any hints?

Upvotes: 3

Views: 846

Answers (2)

Most Noble Rabbit
Most Noble Rabbit

Reputation: 2776

You can do:

League league = new League(Arrays.asList(
        new Team(Arrays.asList(new Player(8), new Player(11))),
        new Team(Arrays.asList(new Player(15), new Player(12))),
        new Team(Arrays.asList(new Player(6), new Player(2), new Player(7)))
));

List<Player> bestPlayersInEachTeam = league.getTeams().stream()
        .map(team -> team.getPlayers().stream()        // Best from each team
                .max(Comparator.comparing(Player::getScore))
                .get())
        .collect(Collectors.toList());

System.out.println(bestPlayersInEachTeam);

Output:

[Player(score=11), Player(score=15), Player(score=7)]

Upvotes: 3

azro
azro

Reputation: 54148

The Team class could have a bestPlayer method

public Player bestPlayer() {
    return players.stream().max(Comparator.comparing(Player::getScore)).orElseThrow();
}

And in the League, it would be easy to get the best player per team:

public List<Player> getTopPlayersFromEachTeam() {
    return this.teams.stream().map(Team::bestPlayer).collect(Collectors.toList());
}

Or all-in-one

public List<Player> getTopPlayersFromEachTeam() {
    return this.teams.stream()
            .map(t -> t.getPlayers().stream().max(Comparator.comparing(Player::getScore)).orElseThrow())
            .collect(Collectors.toList());
}

The .orElseThrow() code just means that if no max player can be found, for example if the list of players of one Team is empty


Test code

League l = new League(Arrays.asList(
        new Team(Arrays.asList(new Player(1), new Player(2), new Player(3))),
        new Team(Arrays.asList(new Player(10), new Player(20), new Player(30))),
        new Team(Arrays.asList(new Player(100), new Player(200), new Player(300)))
));

System.out.println(l.getTopPlayersFromEachTeam()); // [Player{score=3}, Player{score=30}, Player{score=300}]

Upvotes: 6

Related Questions