javacollectionsjava-stream

Is it possible to convert the return type of collect (Collectors.ToList() to LinkedList?


I want to write a function that will create a stream of random numbers:

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class fillRandom {
    public static List<Integer> IntFill(){
        return new Random().ints(10,0,100).boxed().collect(Collectors.toList());

    }
}

And then I want to return it to my LinkedList:

public class Main {

    public static void main(String[] args) throws Exception {
        List linkedList = new LinkedList<Integer>();
        Print printer = new printImpl();
        linkedList = (LinkedList) fillRandom.IntFill();
        printer.print(linkedList);

    }

}

But I get an error Exception in thread "main" java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class java.util.LinkedList

Is it possible to do something to make it work without collect(Collectors.toCollection(LinkedList::new))? If I don't want to return exactly the ArrayList from Random.


Solution

  • According to the documentation of toList, there is no guarantee on the type of list returned, and it specifically asks you to use toCollection

    There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned; if more control over the returned List is required, use toCollection(Supplier).

    If your reason for not using toCollection is simply to avoid using a specific implementation in intFill, and wants to allow the caller to specify what List they want, you can alway give the user that option with a Supplier parameter, just like how toCollection does.

    public static <C extends Collection<Integer>> C intFill(Supplier<C> collectionSupplier){
        return new Random().ints(10,0,100).boxed()
            .collect(Collectors.toCollection(collectionSupplier));
    }
    

    Usage:

    List<Integer> linkedList = fillRandom.intFill(LinkedList::new);
    

    Alternatively, rather than casting, use the LinkedList constructor to create a LinkedList from whatever List is returned by the toList collector.

    List<Integer> linkedList = new LinkedList<>(fillRandom.intFill());
    

    Note that a disadvantage of this is that it will loop over the whole list again, which may not be desirable.