2

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)
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
bbKing
  • 179
  • 1
  • 8
  • If you have s stream, why collect it into a List, then turn that into a stream immediately? This strikes me as a bit of an XY problem. – Chris Sep 09 '22 at 20:16
  • "// if this line commented it doesn't compile" Because it is not a statement :) plain 1+1 wont compile neither, but int i=1+1 will; – Antoniossss Sep 09 '22 at 20:17
  • 1
    @Antoniossss I don't think so. `input.stream().collect(Collectors.toSet())` will compile just fine and I can call `stream()` on the resulting set without assigning it to a set beforehand – bbKing Sep 09 '22 at 20:26
  • @Chris That is exactly what I am trying to do: not store it in an intermediate `List>` – bbKing Sep 09 '22 at 20:28

1 Answers1

5

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) ->
     {
          ...
     },
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46