Passing from list <a> to list <b> when B expands A

I have two clans:

public class A {
   //attibutes and methods
}

public class B extends A {
   //atributes and methods
}

      

Now I have a service that returns a list of elements of type A . Let's call it generateAElements () ;

I want to call this method , filter the list obtained only to keep elements of type B that are also of type A.

List<A> listA = generateAElements();
List<A> listAA = listA.filter( p -> p instanceof B).collect(Collectors.toList());
List<B> listB = new ArrayList<>();
// need to create a new list, iterate overListA and add elements of type B?
for (A itemA : listA) {
    listB.add((B) itemA);       
}

      

Is there an efficient way to do this?

Important: the list can contain a large number of items.

+3


source to share


2 answers


Assuming you are using Java 8+ you can use streams:

List<B> listB = listA
    .stream()
    .filter(B.class::isInstance)
    .map(B.class::cast)
    .collect(Collectors.toList());

      

Of course this can be done in earlier versions of Java, it will likely be more verbose.




A note on terminology: This is not a "casting from List<A>

to List<B>

" - the only things that are done here are individual entries.

+9


source


Streaming version. You just need to do a compatibility check before casting and you can do whatever you want.

List<A> listA = generateAElements();
List<B> listB = new LinkedList<>();
for (A item : listA) {
    // Skip non compatable items
    if(item instanceof B) 
        listB.add((B) item);       
}

      



The key difference from the OP's code is the line if(item instanceof B)

that does the OP's filtering / error checking, but doesn't. (This is technically the same as what the streamed version does, but a little more verbose and much less overhead)

+1


source







All Articles