从列表<a> to List<b> when B extends A

时间:2017-06-05 17:28:13

标签: java list casting java-8 java-stream

I have two clases:

public class A {
   //attibutes and methods
}

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

Now I have a service that returns a List with elements of type A. Lets call it generateAElements();

I want to call that method, filter the List obtained to only keep the elements of type B, which also are 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 may contain a large number of elements.

2 个答案:

答案 0 :(得分:9)

假设您使用的是Java 8+,您可以使用流:

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

当然,这在早期的Java版本中是可行的,它可能更加冗长。

关于术语的说明:这是“从List<A>投射到List<B>” - 这里唯一投放的内容是个人条目。

答案 1 :(得分:1)

免费流媒体版。你只需要在施法前进行兼容性检查,你就可以随心所欲地做任何事情。

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);       
}

与OP代码的主要区别在于行if(item instanceof B),它对OP所需的过滤器/错误检查进行了检查,但没有做到。 (这在技术上与流版本完全相同,但稍微冗长且开销更少)