8

I have a list of list and i want to return the list that have the min size using java Stream.

Here what i tried:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Example {
   public static void main( String[] args )  {
         ArrayList<Integer> list1 = new ArrayList<>();
         list1.add(0);list1.add(2);list1.add(3);

         ArrayList<Integer> list2 = new ArrayList<>();
         list2.add(0);list2.add(2);list2.add(3);list2.add(4);

         System.out.println( getTheMinList(list1,list2).size());    
   }

   public static ArrayList<Integer> getTheMinList(ArrayList<Integer>... lists) {
         return Arrays.stream(lists)
                      .map(list->list.size())
                      /*here i stoped*/
                ;
   }
}

The program should print 3 because the first list has the minimum size.

Note that I can't change the signature of the getTheMinList(). Could anyone please give me a hint?

xmen-5
  • 1,806
  • 1
  • 23
  • 44

2 Answers2

6

You can use Stream.min comparing the List.size:

public static List<Integer> getTheMinList(List<Integer>... lists){
    return Arrays.stream(lists)
            .min(Comparator.comparingInt(List::size))
            .orElse(new ArrayList<>());
}

or possibly better if you could get rid of var-args and unchecked assignment

private static List<Integer> getTheMinList(List<List<Integer>> lists){
    return lists.stream()
            .min(Comparator.comparingInt(List::size))
            .orElse(new ArrayList<>());
}
// invoked as
System.out.println(getTheMinList(List.of(list1, list2)).size());
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 1
    Another suggestion: Try [programming to an interface](https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface). – Naman Nov 20 '18 at 17:09
  • Thank you, i use the var arg because i call the getTheMinList many times with different size arguments. – xmen-5 Nov 20 '18 at 17:40
  • @zakzak `List>` can as well accept varying size outer `List` as an argument if you'd noticed. This means you can call it as `getTheMinList(List.of(List.of(0, 2, 3), List.of(0, 2, 3, 4)))` and `getTheMinList(List.of(List.of(0, 2, 3), List.of(0, 2, 3, 4), List.of(1,2,3)))` as well. – Naman Nov 20 '18 at 17:42
  • yes but i should send a list of list as argument every time, in my program i send many list as argument, like getTheMinList(l1,l2) ,getTheMinList(l1,l2,l3) ans so on...and i m using only java 8. – xmen-5 Nov 20 '18 at 17:43
  • @zakzak it's just a creation of `List>` that you're trying to save possibly Vs the unchecked generics array creation for var-args parameter. – Naman Nov 20 '18 at 17:55
  • just another question, isee that orElse is mandatory, normally every time we have a min, why we should use it.thank you – xmen-5 Nov 20 '18 at 18:08
  • 1
    @zakzak the return type of `min` is `Optional` for which you either check for an `Optional.empty` or can fallback to a default value using [`Optional.orElse`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html#orElse(T)) API. – Naman Nov 20 '18 at 18:11
4

Just another idea...

as @NullPointer suggested, I’d make the method take a List<List<Integer>> rather than the varargs.

Given this change you can simply do:

Collections.min(lists, Comparator.comparingInt(List::size)); 

Short, simple and readable right?

Note that the above will throw a NoSuchElementException upon the collection being empty which may aswell be the expected behaviour you’re wanting but just in case that’s not the the intended behaviour you may want to check for emptiness before the call to min or use the stream approach suggested by @NullPointer which uses the Optional API to return an alternative value if Stream#min returns an empty Optional.

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
  • thank you, i will review my code.in general every list should be not null before the call. – xmen-5 Nov 20 '18 at 17:47
  • 1
    When you stay with varargs, you can still use this solution as simple as `return Collections.min(Arrays.asList(lists), Comparator.comparingInt(List::size));` This uses `Arrays.asList` which creates a lightweight wrapper around the array, allowing to apply the entirety of the Collection API on an existing array… – Holger Nov 21 '18 at 08:54