Как вы фильтруете вложенные циклы, используя потоки и фильтры Java 8?

Как вы фильтруете вложенные циклы, используя потоки и фильтры java8?

Предположим, у меня есть список автомобилей (List<Car>), каждая машина имеет список двигателей (List<Engine>), каждый двигатель, имеющийList<Parts>, В обычной Java эта структура может быть описана как:

for(Car car : cars) {
    for (Engine engine : car.getEngines()) {
        for (Part part : engine.getParts()) {
            // ...
        }
    }
}

Предположим, я инициализирую список автомобилей следующим образом:

List<Car> cars =  new ArrayList<Car>(Arrays.asList(new Car(), new Car(), new Car()));
cars.get(0).setEngines(null);
cars.get(1).setEngines(new ArrayList<Engine>());
cars.get(2).setEngines(new ArrayList<Engine>() {{
    add(new Engine());
    add(null);
    add(new Engine());  
}});

Если я хочу отфильтровать нулиList<Engine>тогда я бы сделал

cars.stream().filter(p -> p.getEngines() != null).forEach(System.out::println);

Если я хочу отфильтровать пустые массивы List, я бы сделал

cars.stream().filter(p -> !p.getEngines().isEmpty()).forEach(System.out::println);

Но как мне удалить нульEngine в 3-й машине и все же оставить два других двигателя прикрепленными к первоначальной структуре списка? Другими словами, можем ли мы перейти на 2-й, 3-й, n-й уровень иерархии с фильтрами Java 8 или фильтры работают только на самом верхнем уровне? Я также пытался использовать.anyMatch()без особой удачи.

просто для дальнейшего уточнения рассмотрим следующий пример: в моем гараже 3 машины. Каждый автомобиль имеет 3 заполнителя для двигателя. Каждый двигатель имеет 3 заполнителя для частей, из которых состоит двигатель:

Car #1: 
 Engine#1: part1, part2, part3
 Engine#2: null, part2, empty
 Engine#3: part1, null, part3
Car #2: 
 Engine#1: part1, part2, part3
 empty:    null, null, null
 null:     null, null, null
Car #3: 
 Engine#1: null, empty, part3
 Engine#2: null, part2, empty
 Engine#3: part1, null, part3

Вопрос: как мы используем Java 8 .filter, чтобы после фильтрации получалось следующее:

Car #1: 
 Engine#1: part1, part2, part3
 Engine#2: part2, 
 Engine#3: part1, part3
Car #2: 
 Engine#1: part1, part2, part3
Car #1: 
 Engine#1: part3
 Engine#2: part2,
 Engine#3: part1,part3

=======================

Другой пример

Ребята, я надеюсь, что этот пример, который я только что составил, более понятен: .. По сути, он такой же, как и выше, только он более многословен, и вместо машин мы можем думать о банках, чтобы минимизировать абстракцию. Для краткости я обнародую все поля, надеюсь, вы не против.

Предположим, что я связан с 4 банками в своем «банковском кошельке»
Bank # 1:
Я физически банк здесь. Я вынужден иметь 3 счета, но только 2 заполнены небольшим количеством денег, а 3 еще не открыт (т. Е. Ноль)
Банк № 2:
Я планирую банк здесь. Создана структура поддержки аккаунта (пустой ArrayList), но аккаунты не добавлены
Банк № 3:
Я заполнил некоторую маркетинговую форму. У меня есть я в их CRM, но никакие счета никогда не будут открыты
Банк № 4:
Этот банк сгорел, в кошельке есть артефакт-заполнитель, который является нулевым.

Следующий код описывает это:

public class Bank_Wallet {

    public static void main(String[] args) {
        List<Bank> banks = new ArrayList<Bank>(Arrays.asList(new Bank(), new Bank(), new Bank(), null));
        // 1st bank with physical accounts, but one of them is null
        banks.get(0).accounts = Arrays.asList(new Account(), null, new Account());
        // 2nd bank with empty accounts  
        banks.get(1).accounts = new ArrayList<Account>();

        System.out.println("RAW original");
        banks.stream().forEach(System.out::println);

        System.out.println("\nFiltered result...   ");
        banks.stream()// get stream
                .filter(p -> p != null) // get rid of null banks
                .filter(p -> p.accounts != null) // get rid of null accounts
                .filter(p -> !p.accounts.isEmpty()) // get rid of empty accounts
                // .filter(p->p.accounts. ?????? ??) ?? how do I remove null account from the remaining bank entry?
                .forEach(System.out::println);

    }// main
}


Классы поддержки здесь:

public class Bank {
    public String name;
    public static int counter = 0;
    public List<Account> accounts;

    public Bank() {
        this.name = "Bank: #" + Bank.counter++;
    }

    @Override
    public String toString() {
        return "Bank [name=" + this.name + ", accounts=" + this.accounts + "]";
    }

public class Account {
    public String name;
    public static int counter;

    public Account() {
        this.name = "Account: " + Account.counter++;
    }

    @Override
    public String toString() {
        return "Account [name=" + this.name + "]";
    }

}

когда вы запустите этот код, вы увидите, что после предложенной фильтрации все, что мне осталось, это

Bank [name=Bank: #0, accounts=[Account [name=Account: 0], null, Account [name=Account: 1]]]

Вопрос: Какой еще фильтр мне нужно добавить в код, чтобы приведенный выше результат не показывал ноль в счетах и ​​при этом сохранял общую структуру (Банк-> Счет-> и т. Д.> И т. Д.)

Bank [name=Bank: #0, accounts=[Account [name=Account: 0], Account [name=Account: 1]]]

Ответы на вопрос(4)

Ваш ответ на вопрос