Home > Net >  Java Stream - Type Inference issue inside a Collector
Java Stream - Type Inference issue inside a Collector

Time:09-10

I have a similar use case to this stack overflow question and was trying to use it without storing the result in a List<List<String>> but instead call stream() on it.

I have a strange compile time error if I don't assign it to List<List<String>> because of type mismatch. To reproduce the issue, just comment out the assignment to output.

The question is why is this compile error occurs? And how to fix it?

public static void main(String args[]) {
    List<String> input = Arrays.asList("RED", "RED", "BLUE", "BLUE", "BLUE", "BLUE", "RED", "RED");
    List<List<String>> output =  // if this line commented it doesn't compile
        input.stream()
            .collect(Collector.of(
                ArrayList::new,
                (accumulator, item) -> {
                    if (accumulator.isEmpty()) {
                        List<String> list = new ArrayList<>();
                        list.add(item);
                        accumulator.add(list);
                    } else {
                        List<String> last = accumulator.get(accumulator.size() - 1);
                        if (last.isEmpty() || last.get(0).equals(item)) {
                            last.add(item);
                        } else {
                            List<String> list = new ArrayList<>();
                            list.add(item);
                            accumulator.add(list);
                        }
                    }
                },
                (left, right) -> {
                    left.addAll(right);
                    return left;
                }
            ));
}

My idea was to use it like:

input.stream()
    .collect(Collector.of(.....))
    .stream()
    .(and do something else)

CodePudding user response:

Functions in Java have no type by itself. They are poly expressions. It means their type should be inferred from the context. It applies for all arguments of the Collector.of().

List<List<String>> output - provides the target type, without it, type inference mechanism has no clue what type of object your Collector is expected to produce.

To make the code compile you can use the type-witness while calling Collector.<all the types of functions used in collector here>of().

The simplest way to make this stream-statement compile is to provide explicit types of arguments of the accumulator:

(List<List<String>> accumulator, String item) ->
     {
          ...
     },
  • Related