2

I would like to get the max value out of a list using java 8 stream methods.

The structure is the following:

  • I read a csv file and store the data of every line in a separate object of type Round.
  • all these Round objects are stored in an ArrayList called arrRound
  • all Round objects have a field: List<Hit> hits
  • a Hit consists of 2 fields: int numberOfGames and int prizeAmount
public class Round{
    private List<Hits> hits; 
}
public class Hits{
    private int numberOfGames;
    private int prizeAmount;
}

What I would like to do is to iterate over all elements of arrRound, get their hits field's getPrizeAmount() method and get the max out of it. I started as the following but can't seem to do it:

public class Main(){
    public void main(String[]args){
        List<Round> arrRound = getRoundFromCSV();
        int maxPrize = arrRound.stream()
                               .forEach(round -> {
                                 round.getHits()
                                      .forEach(hit -> hit.getPrizeAmount());
                                });
    }
}

and I am not able to call max() on the end of the statement.

Thank you for your help in advance!

5 Answers 5

7

You can achieve it by this way :

  • iterate over the Round of the list
  • change from Round object to its List<Hit> hits,
  • use flatMap to go from Stream<List<Hits>> to Stream<Hits>
  • change from Hits to its prizeAmount field
  • get the max if exists
  • if no max (like if list empty or else) return -1

So a solution using Method reference

int maxPrize = arrRoundarrRound.stream()                      // Stream<Round>
                               .map(Round::getHits)           // Stream<List<Hits>>
                               .flatMap(List::stream)         // Stream<Hits>
                               .mapToInt(Hit::getPrizeAmount) // IntStream
                               .max()                         // OptionalInt 
                               .orElse(-1);                   // int

With class lambda and map + flatMap in one :

int maxPrize = arrRoundarrRound.stream()    
                               .flatMap(round -> round.getHits().stream())
                               .mapToInt(hits -> hits.getPrizeAmount())
                               .max()                         
                               .orElse(-1); 
Sign up to request clarification or add additional context in comments.

3 Comments

a more readable solution --> int maxPrize = arrRound.stream() .map(Round::getHits) .flatMap(List::stream) .mapToInt(Hit::getPrizeAmount) .max().orElse(-1);. Although, it's a matter of preference to use method references or not ;-)
I think the original solution was more readable :) This just shows that readability is a subjective thing and it depends more on the reader, at least for these subtle cases.
Thank you very much, it makes sence now... Need to check all methods more deeply one-by-one.
1

Use flatMap:

int maxPrize = arrRound.stream() // Stream<Round>
                       .flatMap(r -> r.getHits().stream()) // Stream<Hit>
                       .mapToInt(Hit::getPrizeAmount) // IntStream
                       .max()
                       .orElse(0);

Comments

1

using reduce

int max1 = arrRound.stream()
        .flatMap(r -> r.getHits().stream())
        .mapToInt(h -> h.getPrizeAmount())
        .reduce(Math::max) //returns OptionalInt
        .orElse(Integer.MIN_VALUE);

or

int max2 = arrRound.stream()
        .flatMap(r -> r.getHits().stream())
        .mapToInt(h -> h.getPrizeAmount())
        .reduce(Integer.MIN_VALUE, Math::max);

Comments

0

Because forEach is a terminal operation. And after you call the forEach on a stream the stream terminates and can't be used again.

Comments

0

using Comparator:

int max2 = arrRound.stream()
            .flatMap(round -> round.getHits().stream())
            .max(Comparator.comparing(Hits::getPrizeAmount))
            .map(Hits::getPrizeAmount)
            .orElse(-1);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.