Как отфильтровать список объектов в списке без изменения исходного списка - PullRequest
1 голос
/ 18 апреля 2020

Упрощенная структура кода выглядит следующим образом:

public class A {
   private List<B> bList;
}

public class B {
   private A a;
   private List<C> cList;
}

public class C {
   private B b;
   private String name;
}

Я бы хотел отфильтровать список объектов A таким образом, чтобы они содержали только те объекты C с именем «123».

Я не хочу менять исходный список. Я могу использовать этот код:

List<A> orginalList;
orginalList.stream()
            .flatMap(a -> a.getBlist().stream())
            .flatMap(b -> b.getClist().stream())
            .filter(c -> "123".equals(c.getName()))
            .collect(toList());

Но этот код вернет мне только отфильтрованный список C объектов. Я хочу получить список объектов A, содержащий список объектов B, который содержит список объектов C, имеющих только имя = "123".

Например, у меня есть что-то подобное:

[
   {
    "bList": [
        {
            "cList": [
                {
                    "name": "123"
                },
                {
                    "name": "555"
                }
            ]
        }
    ]
}

]

Я хочу получить:

 [
   {
    "bList": [
        {
            "cList": [
                {
                    "name": "123"
                }
            ]
        }
    ]
}

]

Ответы [ 3 ]

1 голос
/ 18 апреля 2020

Метод Stream::flatMap выравнивает структуру, что означает, что иерархия разрушена.

Вот способ go:

List<A> filteredList = orginalList.stream()
    .filter(a -> a.getBlist()                   // filter the top List, where the List<B>
            .anyMatch(b -> b.getClist()         // .. has List<C>, where any C
                    .stream()                 
                    .map(C::getName)            // .... has a name
                    .anyMatch("123"::equals)))) // .... is equal to "123"
    .collect(Collectors.toList());              // collect to List
1 голос
/ 19 апреля 2020

Это сохраняет весь путь

Map<Object, List<A>> map = originalList.stream().collect( groupingBy( a -> a.getBList().stream()
    .collect( groupingBy( b -> b.getCList().stream().filter( c -> c.getName().equals( "123" ) )
        .collect( groupingBy( c -> c.getName() ) ), toList() ) ) ) );

Collection<List<A>> c = map.values(); функции определены в java.util.stream.Collectors

0 голосов
/ 18 апреля 2020

Если вы хотите иметь первый элемент, затем отфильтруйте по первой коллекции, а затем используйте anyMatch для проверки, есть ли во внутренней коллекции что-то, что вам нужно.

List<A> orginalList;
orginalList.stream()
            .filter(a -> a.getBlist().stream()
                  .anyMatch(b -> b.getClist().stream()
                        .anyMatch(c -> "123".equals(c.getName())) )
            .collect(toList());

Я думаю, что этот пример может быть полезен для получения идея.

Надеюсь, что это будет полезно для вас!

...