What kind of List<E> does Collectors.toList() return?

69,233

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.

Share:
69,233

Related videos on Youtube

skiwi
Author by

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, 2020

Comments

  • skiwi
    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() nor filter() decide what kind of list to use.
    • Collectors.toList() neither specifies the concrete type of List.

    So, what concrete type (subclass) of List is being used here? Are there any guarantees?

    • jaco0646
      jaco0646 about 4 years
      Since the toUnmodifiableList() method was added in Java 10, it would seem that the mutability of toList() could now be guaranteed.
  • Joeri Hendrickx
    Joeri Hendrickx about 10 years
    You know, you could write that Supplier as a lambda :)
  • skiwi
    skiwi about 10 years
    Would .collect(Collectors.toCollection(LinkedList<Shape>::new)) also work?
  • Rohit Jain
    Rohit Jain about 10 years
    @skiwi No. It doesn't work. Type inference doesn't work with this.
  • yamilmedina
    yamilmedina about 10 years
    Collectors.toCollection((Supplier<List<Shape>>) LinkedList::new) this will work also :)
  • Rohit Jain
    Rohit Jain about 10 years
    @skiwi Or even better with explicit type argument: Collectors.<Shape, List<Shape>>toCollection(LinkedList<Shape>::new)
  • skiwi
    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
    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
    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
    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
    Rohit Jain about 10 years
    @MauriceNaftalin Yes, seems like the issue with eclipse. It compiles on command line, on b129.
  • Hakanai
    Hakanai over 9 years
    Too bad you can't use toCollection() if you want it to create an ImmutableList... you have to write a whooooole new collector.
  • Hakanai
    Hakanai about 9 years
    Keeping in mind that this is just one potential implementation of the API. :)
  • panagiotis
    panagiotis over 6 years
    @Trejkaz You can use .collect(Collectors.collectingAndThen(Collectors.toCollectio‌​n(ArrayList::new), Collections::unmodifiableList))
  • Hakanai
    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
    Stuart Marks over 6 years
    @Trejkaz Correct. In fact we are seriously considering changing the implementation at some point.
  • Stuart Marks
    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
    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
    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
    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
    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
    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 call myCopy = 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
    Gaurav about 2 years
    works flawlessly