Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we extract the main object in streams

I have a FootballTeam class that contains Footballer class. Using streams is it possible to get the FootballTeam from a list of football teams if the FootballTeam contains a Footballer with a particular id. Is it possible to do the below with streams. i.e Get both the targetFootballer and targetTeam;

FootballTeam targetTeam = null;
Footballer targetFootballer = null;

for(FootballTeam team : list.getFootballTeams()){
    for(Footballer f : team.getFootballers()) {
        if(f.getId() == 1){
           targetFootballer = f;
           break;
        }
    }
    if(targetFootballer != null) {
        targetTeam = team;
    }
}
like image 872
user3310115 Avatar asked Mar 07 '23 04:03

user3310115


1 Answers

Don’t think in terms of loops, but rather what high-level operation you’re performing, e.g. finding the first element matching a criteria. The biggest obstacle for expressing such an operation, is that Java methods can not return two values. Using a Map.Entry as a pair type holding both results, you can use

Map.Entry<FootballTeam,Footballer> target = list.getFootballTeams()
    .stream()
    .flatMap(team -> team.getFootballers()
                     .stream()
                     .filter(f -> f.getId() == 1)
                     .map(f -> new AbstractMap.SimpleImmutableEntry<>(team, f)))
    .findFirst()
    .orElse(null);

Since you’re likely want to perform a subsequent operation on these values, you might avoid storing the result in a variable and apply the operation directly, e.g.

list.getFootballTeams()
    .stream()
    .flatMap(team -> team.getFootballers()
                     .stream()
                     .filter(f -> f.getId() == 1)
                     .map(f -> new AbstractMap.SimpleImmutableEntry<>(team, f)))
    .findFirst()
    .ifPresent(e -> {
        FootballTeam targetTeam = e.getKey();
        Footballer targetFootballer = e.getValue();
        // do your action
    });

Here, the action is only executed if a match has been found and you don’t need explicit code dealing with absent values. In the first example, .orElse(null) says that the target should be null if no match has been found, so you have to test for null later-on.

like image 158
Holger Avatar answered Mar 30 '23 16:03

Holger