Search code examples
javajava-8streamflatmap

Iterate over a list of lists and check for a condition using java 8


I'm trying to iterate over a list of a list of elements to test for a given condition, while it is possible with Java 7, I'm interested to know how to do it with java 8 stream.

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class Main2 {
    static String[] positionsThatWillBeCovered = new String[]{"RB", "LB", "MD"};
    static String[] positionsThatWillNotBeCovered = new String[]{"RB", "LB", "MD", "GK"};

    public static void main(String[] args) {
        Position p1 = new Position("RB");
        Position p2 = new Position("LB");
        Position p3 = new Position("MD");

        Player alves = new Player(Arrays.asList(p1, p2));
        Player alba = new Player(Arrays.asList(p2));
        Player xavi = new Player(Arrays.asList(p3));

        Team team = new Team(Arrays.asList(alves, alba, xavi));

        //should print true
        System.out.println(testAllPositionsAreCovered(team, positionsThatWillBeCovered));

        //false
        System.out.println(testAllPositionsAreCovered(team, positionsThatWillNotBeCovered));
    }

    private static boolean testAllPositionsAreCovered(Team team, String[] positionsToCover) {
        for (String positionToCover : positionsToCover) { 
            boolean positionWasCovered = false;
            A : for (Player player : team.getPlayerList()) {
                   for (Position playerPosition : player.getPositions()) {
                        if(playerPosition.getPosition().equals(positionToCover))
                        {
                            positionWasCovered = true;
                            break A;
                        }
                    }
                }
                if (!positionWasCovered) return false;
            }
        return true;
    }
}

class Team {
    private List<Player> playerList;
    Team(List<Player> playerList){
        this.playerList = playerList;
    }

    public List<Player> getPlayerList() {
        return playerList;
    }
}

class Player {
    private List<Position> positions;
    Player(List<Position> positions){
        this.positions = positions;
    }

    public List<Position> getPositions() {
        return positions;
    }
}

class Position {
    private String position;
    //some other fields...
    public Position(String position) {
        this.position = position;
    }

    public String getPosition() {
        return position;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Position position1 = (Position) o;
        return Objects.equals(position, position1.position);
    }

    @Override
    public int hashCode() {
        return Objects.hash(position);
    }
}

a Team contains a list of Players, a Player can play in many positions.

Question: Given a team and a list of positions, I need to know if that every position of the list can be played at least by one player.

I have a solution with Java 7 where we can go throught all positions and check if at least a player can play in it.

I'm interested for the java 8 solution with stream.

Thank you.

EDIT: By The way after the comment of @Holger, I updated my java 7 version of the solution and it is a way better.

Here is the part I changed:

private static boolean testAllPositionsAreCovered(Team team, String[] positionsToCover) {
    for (String positionToCover : positionsToCover) { //"RB", "LB", "MD"
        if (!isThePositionCoveredByAPlayer(team, positionToCover))
            return false;
    }
    return true;
}

private static boolean isThePositionCoveredByAPlayer(Team team, String positionToCover) {
    for (Player player : team.getPlayerList()) {
         for (Position playerPosition : player.getPositions()) {
              if(playerPosition.getPosition().equals(positionToCover))
                return true;
         }
    }
    return false;
}

Solution

  • Use flatMap to combine all the players’ positions into a single Stream:

    public boolean testAllPositionsAreCovered(Team team,
                                              String[] positions) {
    
        Set<String> positionsOfTeams = team.getPlayers().stream()
            .flatMap(p -> p.getPositions().stream())
            .map(Position::getPosition)
            .collect(Collectors.toSet());
        return positionsOfTeams.containsAll(Arrays.asList(positions));
    }