Java группировка объектов по подтипу - PullRequest
1 голос
/ 23 января 2020

У меня есть список суперклассов (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 мне нужно привести объект в l oop.

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

1 Ответ

0 голосов
/ 23 января 2020

Я не знаю ничего лучшего, чем то, что вы описываете, но я бы хотел увидеть его, если он существует.

Проверка instanceof может быть лучшим маршрутом и, вероятно, я сделал бы. Маршрут Map, который вы описали, потребует приведения, потому что тип неизвестен.

Вы можете сделать это с потоками, но для этого потребуется выполнить итерации по списку три раза. Если список небольшой, это может быть хорошо, но я все равно отклоню это в обзоре кода. Тем не менее, это может быть полезно, если вам нужен один цвет.

List<Red> reds = colors.stream()
            .filter(color -> color instanceof Red)
            .map(color -> (Red)color)
            .collect(Collectors.toList());

Тем не менее, я бы не стал использовать это, кроме одного цвета. Как только вы добавите второй цвет, стандартный for l oop подход будет лучше.

...