Search code examples
javajava-8java-stream

Find the min and max number from a Collection using Java streams


Below is the code snippet which, as expected, is failing at compile time.

What I really want to do is to find the min and max from all the lists using streams.

public class Delete {

   public static void main(String[] args) {

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 677, 0);
      List<Integer> list1 = Arrays.asList(11, 12, 23, 34, 25, 77);
      List<Integer> list2 = Arrays.asList(12, 21, 30, 14, 25, 67);
      List<Integer> list3 = Arrays.asList(41, 25, 37, 84, 95, 7);

      List<List<Integer>> largeList = Arrays.asList(list, list1, list2, list3);

      System.out.println(largeList.stream().max(Integer::compare).get());
      System.out.println(largeList.stream().min(Integer::compare).get());
   }

}

Solution

  • You have to flatten the elements of all the Lists into a single Stream<Integer> in order for your code to work :

    System.out.println(largeList.stream().flatMap(List::stream).max(Integer::compare).get());
    System.out.println(largeList.stream().flatMap(List::stream).min(Integer::compare).get());
    

    This is not very efficient, though, since you process the Lists twice in order to find both min and max, and you can get the same data (and more) in a single processing by using IntStream::summaryStatistics() :

    IntSummaryStatistics stats = largeList.stream().
                                          .flatMap(List::stream)
                                          .mapToInt(Integer::intValue)
                                          .summaryStatistics();
    System.out.println(stats.getMin());
    System.out.println(stats.getMax());
    

    Here's another solution available since Java 12:

    System.out.println (largeList.stream()
                                 .flatMap(List::stream)
                                 .collect(Collectors.teeing(
                                              Collectors.maxBy (Integer::compare),
                                              Collectors.minBy (Integer::compare),
                                              List::of
                                         )));
    

    Using Collectors.teeing allows you to apply two Collectors on the same Stream, and then do whatever you wish on the result of the two Collectors. In this example the first Collector will compute the maximum element, the second Collector will compute the minimum element, and the two numbers will be collected into a single List. The output is a List<Optional<Integer>>, where the first element holds the maximum and the second element holds the minimum.