Make an ArrayList of class C from a List of interface I

Viewed 99

Considering these elements :

An interface I :

public interface I {
    int getType();
}

A class C :

public class C implements I {
    @Override
    public int getType() { return 0; }
}

Given a list Of I, how can I make an ArrayList of C using Java 8 ?

Here is what I tried :

public void foo(List<? extends I> listI) {

    List<C> listC = new ArrayList<>((List<C>)listI.stream()
            .filter(o -> o.getType() == 0)
            .collect(Collectors.toList())
    );
}

And the warning I got :

Unchecked cast: 'java.util.List<capture<? extends I>>' to 'java.util.List<C>'

3 Answers

You'll first need to perform a filter intermediate operation to retain all the objects of type C and then a map to perform the transformation i.e:

List<C> listC = listI.stream().filter(e -> e instanceof C).map(e -> (C) e).collect(Collectors.toCollection(ArrayList::new));

Also, when you perform a collect operation you need not use the ArrayList constructor to create a new list rather just use Collectors.toCollection(ArrayList::new) and assign that directly to listC.

C.getType() may return 0, but other implementations of I may do too, so you can't simply check getType() == 0.

To get instances of C, you've got to filter using instanceof:

.filter(o -> o instanceof C)

which yields a Stream<? extends I>; then cast to C to get a Stream<C>:

.map(o -> (C) o)

Here is the solution by StreamEx

List<C> listC = StreamEx.of(listI).select(C.class).toList();

It's simple, short and concise to me.

Related