if stream().filter is empty

Viewed 504

I want to know how to execute code from a stream if the filter does not find values and finds it, an example code:

 @Transactional
public void change(ClassName dep){
    // code
    dep.getFoo()
            .stream()
            .filter(f -> f.getName().equals(doo.getName))
            
}

if the filter has a value then:

user.setFoo(f);

if there is no value in the filter then:

Foo foo = new Foo();
foo.setName("Exp");
user.setFoo(foo);
2 Answers

I would suggest creating a constructor for Foo accepting name.

You can then extract the name with default value of Optional:

Foo foo = dep.getFoo()
        .stream()
        .filter(f -> f.getName().equals(doo.getName))
        .findAny().orElse(new Foo("Exp"));
user.setFoo(foo);

As Holger cleverly noticed using orElseGet would avoid executing the Supplier in case the Optional is not empty (beneficial if the computation is complex or side effects occur):

Foo foo = dep.getFoo()
        .stream()
        .filter(f -> f.getName().equals(doo.getName))
        .findAny().orElseGet(() -> new Foo("Exp"));
user.setFoo(foo);

Since java 11 you can use ifPresentOrElse:

dep.getFoo()
        .stream()
        .filter(f -> f.getName().equals(doo.getName))
        .findAny()
        .ifPresentOrElse(user::setFoo, () -> user.setFoo(new Foo("Exp")));

P.S.: If you cannot create the constructor, you can just create the method to provide it and use it in the above snippet:

public static Foo defaultFoo() {
    Foo foo = new Foo();
    foo.setName("Exp");
    return foo;
}

Try next example:

Foo foo = new Foo();
foo.setName("Exp");


user.setFoo(dep.getFoo()
            .stream()
            .filter(f -> f.getName().equals(doo.getName))
            .findFirst().orElse(foo);

Because filter could return more then one object, you should to limit it on one object. findFirst will return object of type Optional and orElse will return foo in case optional is empty. In other case you will get founded foo.

Related