What kind of List<E> does Collectors.toList() return?
Solution 1
So, what concrete type (subclass) of List is being used here? Are there any guarantees?
If you look at the documentation of Collectors#toList()
, it states that - "There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned". If you want a particular implementation to be returned, you can use Collectors#toCollection(Supplier)
instead.
Supplier<List<Shape>> supplier = () -> new LinkedList<Shape>();
List<Shape> blue = shapes.stream()
.filter(s -> s.getColor() == BLUE)
.collect(Collectors.toCollection(supplier));
And from the lambda, you can return whatever implementation you want of List<Shape>
.
Update:
Or, you can even use method reference:
List<Shape> blue = shapes.stream()
.filter(s -> s.getColor() == BLUE)
.collect(Collectors.toCollection(LinkedList::new));
Solution 2
Navigating through Netbeans (Ctrl + Click), I landed in this code. It seems to be using an ArrayList as Supplier.
public static <T> Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
Solution 3
It doesn't matter, but the concrete type is non-generic as indeed all types are non-generic at runtime.
So, what concrete type (subclass) of List is being used here? Are there any guarantees?
I don't think so, but ArrayList or LinkedList seem likely.
Related videos on Youtube
skiwi
Studied Computer Science at the Eindhoven University of Technology. I used to be quite experienced in working with Java and have experience in PHP/MySQL/Javascript/jQuery/CSS/HTML aswell. Nowadays I work more often with C# and have some side projects in other languages. Feel free to check what I am working at on Github or to contact me at LinkedIn.
Updated on March 29, 2020Comments
-
skiwi about 4 years
I am reading State of the Lambda: Libraries Edition, and am being surprised by one statement:
Under the section Streams, there is the following:
List<Shape> blue = shapes.stream() .filter(s -> s.getColor() == BLUE) .collect(Collectors.toList());
The document does not state what
shapes
actually is, and I do not know if it even matters.What confuses me is the following: What kind of concrete
List
does this block of code return?- It assigns the variable to a
List<Shape>
, which is completely fine. -
stream()
norfilter()
decide what kind of list to use. -
Collectors.toList()
neither specifies the concrete type ofList
.
So, what concrete type (subclass) of
List
is being used here? Are there any guarantees?-
jaco0646 about 4 yearsSince the
toUnmodifiableList()
method was added in Java 10, it would seem that the mutability oftoList()
could now be guaranteed.
- It assigns the variable to a
-
Joeri Hendrickx about 10 yearsYou know, you could write that Supplier as a lambda :)
-
skiwi about 10 yearsWould
.collect(Collectors.toCollection(LinkedList<Shape>::new))
also work? -
Rohit Jain about 10 years@skiwi No. It doesn't work. Type inference doesn't work with this.
-
yamilmedina about 10 years
Collectors.toCollection((Supplier<List<Shape>>) LinkedList::new)
this will work also :) -
Rohit Jain about 10 years@skiwi Or even better with explicit type argument:
Collectors.<Shape, List<Shape>>toCollection(LinkedList<Shape>::new)
-
skiwi about 10 years@RohitJain Perhaps
Collectors.toCollection(LinkedList<Shape>::new
works now with Java 8 b129 build, as some type interference has been improved. I don't know exactly how to try it myself though and Netbeans 8.0 doesn't support the improved type interference yet it seems (on an older testcase -> See stackoverflow.com/questions/21751830/…) -
Rohit Jain about 10 years@skiwi I see. I haven't yet got the new build on my machine. Perhaps, I would download it today.
-
Maurice Naftalin about 10 years@skiwi @RohitJain Type inference is better than you think: you don't need to provide any explicit type information apart from the target type. So you can just write
List<Shape> shapeList = ...collect(Collectors.toCollection(LinkedList::new));
-
Rohit Jain about 10 years@MauriceNaftalin It isn't compiling. I've currently
b108
on my machine. Has it been improved in later build? Of course I will download the latest build, but that will take time. -
Rohit Jain about 10 years@MauriceNaftalin Yes, seems like the issue with eclipse. It compiles on command line, on
b129
. -
Hakanai over 9 yearsToo bad you can't use toCollection() if you want it to create an ImmutableList... you have to write a whooooole new collector.
-
Hakanai about 9 yearsKeeping in mind that this is just one potential implementation of the API. :)
-
panagiotis over 6 years@Trejkaz You can use
.collect(Collectors.collectingAndThen(Collectors.toCollection(ArrayList::new), Collections::unmodifiableList))
-
Hakanai over 6 years@panos unmodifiableList is a "Claytons immutable", but you end up writing your own collector if you want an actually-immutable collection, e.g. one of Guava's. Thinking about it a bit, though, the real shame is that toList() doesn't return an immutable list in the first place.
-
Stuart Marks over 6 years@Trejkaz Correct. In fact we are seriously considering changing the implementation at some point.
-
Stuart Marks over 6 years@Trejkaz Agree, toList should have returned an immutable in the first place, but oh well, it didn't. We hope to change this at some point. Also, what is a "Claytons immutable"?
-
Hakanai over 6 years@StuartMarks a "Claytons X" is "an X you have when you're not having an X", in reference to "the drink you have when you're not having a drink". The implication is that
Collections.unmodifiableList()
doesn't make an immutable list, because someone has a reference to the list it's wrapping and can mutate that. OTOH, the method could have created an immutable copy. -
Stuart Marks over 6 years@Trejkaz Ha, ok, thanks. That reference doesn't seem to have made it to the USA. I was looking all over for "Claytons" with respect to immutability and data structures and I couldn't find anything. :-)
-
DodgyCodeException over 5 years@Trejkaz if you have an unmodifiable list but the only reference to the wrapped list is the
Collections.unModifiableList
wrapper itself, does that make the list immutable? -
Hakanai over 5 years@DodgyCodeException possibly, but if my code receives an instance of that, it has no way to know for sure, so I have to treat it as potentially mutable anyway. :(
-
Holger over 4 years@Trejkaz with recent versions,
.collect(Collectors.collectingAndThen(Collectors.toList(), List::copyOf))
will give you a truly immutable list (but you have to cope with the no-null
policy). Any receiver can simply callmyCopy = List.copyOf(inputList);
to be sure to have a truly immutable list, as that method will do nothing if the list is already immutable. I suppose, for Guava, a similar thing exists. -
Gaurav about 2 yearsworks flawlessly