8

I am reading the newly released Java 8 in Action and found there is a piece of code pasted from Chapter 5 not compiling:

    List<Integer> numbers1 = Arrays.asList(1, 2, 3);
    List<Integer> numbers2 = Arrays.asList(3, 4);
    List<int[]> pairs =
    numbers1.stream()
    .flatMap((Integer i) -> numbers2.stream()
    .map(j -> new int[]{i, j})
    )
    .collect(toList());

Eclipse says: "Type mismatch: cannot convert from List<Object> to List<int[]>"

And after comparing with what the author gave on Github, the following compiled:

    List<Integer> numbers1 = Arrays.asList(1, 2, 3);
    List<Integer> numbers2 = Arrays.asList(3, 4);
    List<int[]> pairs =
    numbers1.stream()
    .flatMap((Integer i) -> numbers2.stream()
    .map((Integer j) -> new int[]{i, j})
    )
    .collect(toList());

The only change is from "j" to "(Integer j)".

But isn't the first version completely equivalent to the second with the syntax sugar provided by Java 8? Why does Java refuse to compile it?

Thanks

BTW:

java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) Client VM (build 25.20-b23, mixed mode)
Tony Lang
  • 170
  • 1
  • 9
  • *Argh* this is printed in a book?! – tilois Sep 15 '14 at 18:20
  • Not entirely. Modified a little bit to make the question obvious. – Tony Lang Sep 15 '14 at 18:34
  • Edited the title to reflect that the root cause is in Eclipse. – Tony Lang Sep 15 '14 at 18:35
  • To add a bit of reasoning: I find `List` a... suboptimal representation of a list of Integer tuples. – tilois Sep 15 '14 at 18:39
  • @tilois You are right, I wish Scala tuples could be used here. Actually this piece of code is from the answer of a quiz in the book, and the author said in the question: "For simplicity, you can represent a pair as an array with two elements." – Tony Lang Sep 15 '14 at 18:46

1 Answers1

15

First, correcting your terminology: when you say syntax sugar, what you really are asking about is type inference, that when asked to infer a type for j in the inner lambda, that the compiler fails to come up with the right type.

Second, correcting your data: The error messages you cite are not coming from the JDK compiler; they're coming from Eclipse.

This is just an Eclipse bug. The reference compiler (javac from Oracle JDK) handles your first example just fine.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • 2
    +1 and adding a further diagnostic bit: `Stream pairs = numbers1.stream().flatMap(i -> numbers2.stream().map(j -> new int[] {i, j}));` compiles fine, so only the last step (`.collect()`) is where the inference fails. – Marko Topolnik Sep 15 '14 at 18:17
  • Confirmed it is just about Eclipse. javac created the class file just fine. Thanks/ – Tony Lang Sep 15 '14 at 18:30
  • Any word on how to get Eclipse to play nice with these Lambdas? – Yoshiya Jul 01 '15 at 20:50