Assign a value based on condition using Java Stream if present or else

Viewed 1136

I want to set a value to a string if an Optional is present else get it from a list based on a condition. I have tried many ways but not able to get it. I am new to Streams so need help.

Basically my condition is this in traditional way -

        String rel = ""
        if(release.isPresent()){
            rel = release.get();
        }
        else{
            for(Release r: project.getReleases()){
                if(r.isActive() == true){
                    rel = r.getName();
                }
            }
        }

This is what I have written, but it doesn't work. I am getting error in the orElse part -

rel = release.ifPresent(r-> release.get())
                .orElse(
                    project.getReleases()
                    .stream()
                    .filter( r -> r.isActive() == true)
                    .findFirst()
                    .map(r->r.getName()));

Can you please suggest what is the correct way to do this ? Thanks in advance for any help.

3 Answers

This is what you want in case you use or newer (I recommend you to tag the version used):

String rel = release
        .or(() -> project.getReleases().stream()
                                       .filter(Release::isActive)
                                       .map(Release::getName)
                                       .findFirst())
        .orElse("");

Basically Optional#or returns either the present value from the original Optional or provides a Supplier<Optional> providing such value in lazy way (will not be called in case the former value is present).

Use the advantage that Stream#findFirst returns Optional hence such call is compatible with the method needs. Finally call orElse("") as the last possible value if no usable value was present in the previous attempts.

You should use Optional#orElseGet for this

Why orElseGet and not orElse ?

Because orElseGet accepts a Supplier which will only be invoked if your Optional is empty. So you won't have the overhead of Stream creation etc.

Example

String rel = release.orElseGet(() -> project.getReleases()
                                            .stream()
                                            .filter(Release::isActive)
                                            .map(Release::getName)
                                            .findFirst()
                                            .orElse(""));

you can do

release.orElse(project.getReleases()
               .stream().filter(Release::isActive).findFirst().map(Release::getName).orElse(""));
Related