How do you filter nested loops using Java 8 streams and filters?

java 8 stream practice problems
java-stream nested loop
java stream filter
java 8 stream filter boolean true
java stream flatmap
java 8 stream filter(predicate)
java 8 stream filter json array
java-stream filter return boolean

How do you filter nested loops using java8 streams and filters?

Suppose I have a list of cars (List<Car>), each car having a list of Engines (List<Engine>), each engine having a List<Parts>. In regular Java this structure can be described as:

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

Suppose I initialise the list of cars as:

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

If I want to filter out nulls of List<Engine>, then I would do

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

If I want to filter out empty arraylists of List, then I would do

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

But how do I remove the null Engine 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 .anyMatch(), without much luck.

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:

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

Question: how do we use Java 8 .filter, such that when after filtering I get the following:

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

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

Another example

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.

Suppose I am affiliated with 4 banks in my 'bank wallet' Bank#1: 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) Bank #2: I plan to bank here. Account support structure is created (empty ArrayList), but no accounts are added Bank #3: I filled out some marketing form. They have me in their CRM but no accounts will ever be opened Bank #4: This bank burned down, there is an artifact placeholder in the wallet, which is null.

The following code describes this:

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
}

The support classes are here:

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 + "]";
    }

}

when you run this code you will see that after suggested filtering all I am left with is

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

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)

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

The stream equivalent of

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

is

cars.stream()
    .flatMap(car -> car.getEngines().stream())
    .flatMap(engine -> engine.getParts().stream())
    .forEach(part -> { /* ... */ });

The ... code will however not have access to car and engine.

To check for null, you can check in two places:

cars.stream()
    .flatMap(car -> car.getEngines().stream())
    .filter(engine -> engine != null)
    .flatMap(engine -> engine.getParts().stream())
    .forEach(part -> { /* ... */ });

or

cars.stream()
    .flatMap(car -> car.getEngines()
                       .stream()
                       .filter(engine -> engine != null))
    .flatMap(engine -> engine.getParts().stream())
    .forEach(part -> { /* ... */ });

How to filter nested loops using Java 8 streams and filters?, There is nice method Collection.removeIf(Predicate<? super E> filter) method. For example: class Example { public static void main(String[] args){ List<Parent>​  Trying to get my head round the Java 8 streams syntax with a simple example. Had a look at the other similar questions on this topic, but could not find any solutions that would match my example and would work for me. Basically I am trying to refactor the following snippet with two nested loops to use the new stream API:

And why do you not simply write this ?

cars.stream()
    .filter(car -> notEmpty(car.getEngines()))
    .filter(car -> car.getEngines().stream().allMatch(engine -> notEmpty(engine.getParts())))
    .forEach(System.out::println);

public static <T> boolean notEmpty(Collection<T> collection) {
   return collection != null && !collection.isEmpty();
}

Replace Nested Loops with flatMap, avoided by using flatMap(). Using 'flatMap()' makes code much more readable and can be combined with other stream functions. Iterating over nested collections; Nested Stream::forEach; Deep nested loops Minimum Java version​, 8. Remediation isEmpty()).forEach(cell -> { cell.stream().filter(element -> !​element. How can I do the following nested loop using java stream? Java 8 Stream Nested for loop. Is there any reason for using a stream? You do not have to migrate

How about following?

    List<Car> cars = new ArrayList<Car>(Arrays.asList(new Car("C0"), new Car("C1"), new Car("C2")));
    cars.get(0).setEngines(new ArrayList<Engine>());
    cars.get(1).setEngines(new ArrayList<Engine>());
    cars.get(2).setEngines(Arrays.asList(new Engine("C2E1"), new Engine("C2E2"), null));

    cars.stream().filter(c -> Objects.nonNull(c.getEngines())).forEach(c -> {
        System.out.printf("Car %s ", c);
        c.getEngines().stream().filter(e -> Objects.nonNull(e) && Objects.nonNull(e.getParts())).forEach(e -> {
            System.out.printf(" Engine %s ", e);
            e.getParts().stream().filter(p -> Objects.nonNull(p))
                    .forEach(p -> System.out.printf("Part %s", p));
        });
        System.out.println();
    });

Produces following :

Car C0

Car C1

Car C2 Engine C2E1 Part DefaultPart Engine C2E2 Part DefaultPart

Have overriden "toString" for Car/Engine/Part classes.

Hope this helps.

Java 8 stream - multiple filters example, Learn to filter a stream of objects using multiple filters and process filtered objects by either collecting to a new list or calling method on objects. How to Filter Collections in Java 8 with Streams and Predicates Java 8 provides excellent features to support filtering of elements in Java Collections. Prior to Java 8, only better way to filter elements is by using foreach loop or iterating over Collection using Iterator and selecting required object, leaving out rest.

you can use removeIf() like following:

 cars.removeIf(car -> car.getEngines() == null);

 cars.forEach(c->System.out.println("Car :"+c);

A Guide to Streams in Java 8: In-Depth Tutorial With Examples, First of all, Java 8 Streams should not be confused with Java I/O it loops over the stream elements, calling the supplied function on asList("Mark", "​Zuckerberg")); List<String> namesFlatStream = namesNested.stream() . They return an Optional since a result may or may not exist (due to, say, filtering): Java 8 Streams: An Intro to Filter, Map and Reduce Operations Learn more on Java with our tutorial Bridging Android and Java in Android Development on SitePoint.

Towards More Functional Java - Digging into Nested , In this example, we'll look at how to use Java 8 streams to dig into a nested We'​ll use map and filter operations on the stream, and also introduce a new of C2 , and return null if we exit the loops without having found anything. But if things like transformation or filtering take a significant amount of time,  Nested Loop in Java In this article, you will learn about nested loops and how it works with the help of examples.

Single vs. Multiple Filters in the Java Stream API, One of the key features of Java 8 is the stream. It is frequently used in conjunction with lambdas, and one of them is the filter. Let's consider the  Awesome! We're migrating our code base to Java 8. We'll replace everything by functions. Throw out design patterns. Remove object orientation. Right! Let's go! Wait a minute Java 8 has been out for over a year now, and the thrill has gone back to day-to-day business.

How to Filter Collections in Java 8 with Streams and , Java 8 provides excellent features to support filtering of elements in Java Java 8 Stream is very efficient replacement of looping both design  On this page we will provide java 8 Stream filter() example. It is an intermediate operation and can be used with reduce(), collect(), map() etc. We filter a collection for a given Predicate instance. filter() method returns a Stream instance which consists only filtered element on the basis of given Predicate.

Comments
  • run map over each entry in the outer list. The map function should filter out what you don't want.
  • Could you be more specific in what you're trying to achieve with your loops ? I think Andreas raised a good point showing me that I made too many assumptions about what you are looking for, because your question is not specific enough. Just give us a sample input along with the desired output
  • Is that something to be displayed or something to be collected ?
  • @JavaFan collecting this would involve either mutating the cars or creating new ones, which one is expected ?
  • Did you know that you can simply use the result of Arrays.asList everywhere, where a List is required, i.e. that you don’t have to clutter your code with gazillion different attempts of creating and filling ArrayLists?
  • He wants to display the cars, not the parts (from my understanding). That's why flatMap cannot be used here, or not this way. We don't want to lose the reference to the car. Also, all your snippets may throw a NullPointerException
  • this is really good but as @Dici pointed out, i want to display the cars not the parts themselves.
  • @JavaFan How does the text "But how do I remove the null Engine in a 3rd car and yet keep two other engines attached to the original list structure?" jive with only wanting the car? If you only want to car, what is the entire point of filtering the engine list? And what does any of that have to do with the part list? Of course, the concept of a car having more than one engine is unusual to begin with.
  • getEngines() returns List<Engine> (or similar), which doesn't have getParts.
  • The System.out::println will be called once for each Car, which is very different result than the for loop code, which will execute ... for each Part.
  • @Andreas I think we understood the question differently. To be fair, it's not very well explained what we should answer to. I took the first snippet as pseudo-code to illustrate the "levels", not as actual code. If it is actual code then you're absolutely right, but it would sound odd to print the cars several times
  • just one second guys I will provide an example in the original post what I want. Apologies for not being clear