Search code examples
javalambdafunctional-programmingjava-8java-stream

Getting sublist from a Java list with nth elements that fulfills a condition with streams


I have a very simple use case

Given a list of letters with A and Bs, I want to get the sublist that contains the first N Bs, for example:

  • f(3, [A A A B A B A B A A]) = [A A A B A B A B]
  • f(2, [A A A B A B A B A A]) = [A A A B A B]
  • f(1, [A A B A B A]) = [A A B]
  • f(0, [A A B A B]) = []

By following an imperative approach, this is relatively easy, count until we find N Bs, and then get the sublist until that position.

However, I couldn't find any functional solution with lambdas, since the operation on every node seems to be independent from the others (which I guess make sense for parallelization).


Solution

  • If your input is a List with fast random access, you can solve your problem using the stream of indices:

    public static List<String> f(int n, List<String> input) {
        int fence = IntStream.range(0, input.size())
                             .filter(idx -> input.get(idx).equals("B")) // leave only B's
                             .skip(n-1)
                             .findFirst() // an index of n-th B
                             .getAsInt(); // with throw NoSuchElementException if not enough B's
        return input.subList(0, fence+1);
    }
    

    Usage example:

    System.out.println(f(3, Arrays.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A")));
    System.out.println(f(2, Arrays.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A")));
    System.out.println(f(1, Arrays.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A")));
    

    However despite I love Stream API I would solve this problem imperatively.