Reputation: 21
I'm not sure why this code doesn't compile (case 1)
List list = new LinkedList<>();
List<Long> longList = list.stream()
.map(value -> (Long) ((Map) value).get("id"))
.collect(Collectors.toList());
but this code compile successfully (case 2)
List list = new LinkedList<>();
Stream<Long> longStream = list.stream()
.map(value -> (Long) ((Map) value).get("id"));
List<Long> longList = longStream.collect(Collectors.toList());
and this code compile successfully to (case 3)
List<Object> list = new LinkedList<>();
List<Long> longList = list.stream()
.map(value -> (Long) ((Map) value).get("id"))
.collect(Collectors.toList());
My colleague suppose that this connected with
Replace all type parameters in generic types with their bounds or
Object
if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
from Java SE tutorial
So in case 1 list is unbounded that's why compiler replace all types with Object
.
In case 2 we create generic Stream
of Long
and this stream can't be unbounded. Compiler do nothing.
In case 3 we have List
of Object
and there is no replacing during compilation.
The question is what the real difference between this 3 cases?
Upvotes: 2
Views: 1235
Reputation: 533530
Your List list
is a raw type and this has the effect of making all the methods you call on it raw types as well, even though you might later return a generic type. i.e. you map() notional returns a Stream<Long>
but the compiler only sees it as a non-generic Stream
By assigning it to a variable, you are effectively casting it to a generic.
What I suggest you do is
List<Map<String, Long>> list = new LinkedList<>();
List<Long> longList = list.stream()
.map(value -> value.get("id"))
.collect(Collectors.toList());
Upvotes: 3