title: How do you filter nested loops using Java 8 streams and filters?
body: <p>How do you filter nested loops using java8 streams and filters?</p>
  
  <p>Suppose I have a list of cars (<code>List&lt;Car&gt;</code>), each car having a list of Engines (<code>List&lt;Engine&gt;</code>), each engine having a <code>List&lt;Parts&gt;</code>.
  In regular Java this structure can be described as:</p>
  
  <pre><code>for(Car car : cars) {
      for (Engine engine : car.getEngines()) {
          for (Part part : engine.getParts()) {
              // ...
          }
      }
  }
  </code></pre>
  
  <p>Suppose I initialise the list of cars as:</p>
  
  <pre><code>List&lt;Car&gt; cars =  new ArrayList&lt;Car&gt;(Arrays.asList(new Car(), new Car(), new Car()));
  cars.get(0).setEngines(null);
  cars.get(1).setEngines(new ArrayList&lt;Engine&gt;());
  cars.get(2).setEngines(new ArrayList&lt;Engine&gt;() {{
      add(new Engine());
      add(null);
      add(new Engine());  
  }});
  </code></pre>
  
  <p>If I want to filter out nulls of <code>List&lt;Engine&gt;</code>, then I would do</p>
  
  <pre><code>cars.stream().filter(p -&gt; p.getEngines() != null).forEach(System.out::println);
  </code></pre>
  
  <p>If I want to filter out empty arraylists of List, then I would do</p>
  
  <pre><code>cars.stream().filter(p -&gt; !p.getEngines().isEmpty()).forEach(System.out::println);
  </code></pre>
  
  <p>But how do I remove the null <code>Engine</code> in a 3rd car and yet keep two other engines attached to the original list structure? In other words, can we go into the 2nd, 3rd, nth level of hierarchy with Java 8 filters or do filters only work on the top-most layer? I also tried to use <code>.anyMatch()</code>, without much luck.  </p>
  
  <p>just to further clarify, consider the following example:
  I have 3 cars in my garage.  Each car has 3 placeholders for engine.  Each engine has 3 placeholders for parts that make up the engine:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Question: how do we use Java 8 .filter, such that when after filtering I get the following:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>=======================</p>
  
  <h1>Another example</h1>
  
  <p>Guys I hope this example that I just made up is clearer:.. Essentially it is the same as above only it is more verbose and instead of cars we can think of banks to minimize abstraction.   For conciseness I make all fields public, I hope you don't mind.  </p>
  
  <p>Suppose I am affiliated with 4 banks in my 'bank wallet'<br>
  Bank#1: <br>
    I physically bank here.  I am forced to have 3 accounts, but only are 2 filled with some cash and 3rd is yet to opened (ie null)<br>
  Bank #2:<br>
    I plan to bank here. Account support structure is created (empty ArrayList), but no accounts are added<br>
  Bank #3:<br>
   I filled out some marketing form.  They have me in their CRM but no accounts will ever be opened<br>
  Bank #4:<br>
   This bank burned down, there is an artifact placeholder in the wallet, which is null.  <br></p>
  
  <p>The following code describes this:</p>
  
  <pre><code>public class Bank_Wallet {
  
      public static void main(String[] args) {
          List&lt;Bank&gt; banks = new ArrayList&lt;Bank&gt;(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&lt;Account&gt;();
  
          System.out.println("RAW original");
          banks.stream().forEach(System.out::println);
  
          System.out.println("\nFiltered result...   ");
          banks.stream()// get stream
                  .filter(p -&gt; p != null) // get rid of null banks
                  .filter(p -&gt; p.accounts != null) // get rid of null accounts
                  .filter(p -&gt; !p.accounts.isEmpty()) // get rid of empty accounts
                  // .filter(p-&gt;p.accounts. ?????? ??) ?? how do I remove null account from the remaining bank entry?
                  .forEach(System.out::println);
  
      }// main
  }
  </code></pre>
  
  <p><br>
  The support classes are here:</p>
  
  <pre><code>public class Bank {
      public String name;
      public static int counter = 0;
      public List&lt;Account&gt; 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 + "]";
      }
  
  }
  </code></pre>
  
  <p>when you run this code you will see that after suggested filtering all I am left with is <br></p>
  
  <pre><code>Bank [name=Bank: #0, accounts=[Account [name=Account: 0], null, Account [name=Account: 1]]]
  </code></pre>
  
  <p>Question:
  What other filter do I need do add to the code to get the above result not show null in the accounts and yet retain the overall structure (Bank->Account->etc->etc)</p>
  
  <pre><code>Bank [name=Bank: #0, accounts=[Account [name=Account: 0], Account [name=Account: 1]]]
  </code></pre>