我有一个父类(super class)列表 ( List<SuperClass> classes = ...
),我想根据其子类型将其拆分为单独的列表。 我想最终得到用子类型参数化的列表,即 List<A> aClasses = ...
不是List<SuperClass> aClasses = ...
给定此类层次结构:
abstract class SuperClass {...}
class A extends SuperClass {...}
class B extends SuperClass {...}
class C extends SuperClass {...}
这是我到目前为止所做的,它确实有效。问题是,当迭代 aClasses
时, bClasses
,和cClasses
列表,我需要在循环内转换对象。
List<SuperClass> classes = ... // mix of A, B, and C
Map<Class<? extends SuperClass>, List<SuperClass>> grouped = classes.stream()
.collect(Collectors.groupingBy(SuperClass::getClass, Collectors.toList()));
List<SuperClass> aClasses = grouped.get(A.class);
List<SuperClass> bClasses = grouped.get(B.class);
List<SuperClass> cClasses = grouped.get(C.class);
我知道这可行,但我正在寻找更多简洁代码(可能使用流)。尽管写完下面的代码后,我认为我可以用流做的任何事情都可能与下面的代码一样“复杂”。
List<A> aClasses = new ArrayList<A>();
List<B> bClasses = new ArrayList<B>();
List<C> cClasses = new ArrayList<C>();
for (SuperClass superClass : classes) {
if (superClass instanceof A) {
aClasses.add(superClass);
}
else if (superClass instanceof B) {
bClasses.add(superClass);
}
else if (superClass instanceof C) {
cClasses.add(superClass);
}
}
生成的类将输入到具有以下签名的方法中:
void processA(List<A> aClasses);
void processB(List<B> bClasses);
void processC(List<C> cClasses);
我不会这样做:processA((List<A>) (List) aClasses);
最佳答案
我不知道有什么比你描述的更好的方法,但我想看看它是否存在。
instanceof
检查可能是最好的路线,也可能是我会做的。您描述的 Map
路线需要转换,因为类型未知。
您可以使用流来完成此操作,但这需要迭代列表三次。如果列表很小,那可能没问题,但我仍然会在代码审查中拒绝这一点。也就是说,如果您需要一种颜色,它可能会很有用。
List<Red> reds = colors.stream()
.filter(color -> color instanceof Red)
.map(color -> (Red)color)
.collect(Collectors.toList());
尽管如此,除了单一颜色之外我不会使用它。添加第二种颜色后,标准 for
循环方法会更好。
关于Java 按子类型对对象进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59882690/