hudi
hudi

Reputation: 16525

How to rewrite java loop with saving temporary result to java8 stream

Is there some nice way to rewrite the following loop, in which I am saving temporary results, using Java 8 Stream?

    Integer resultByCon1 = null, resultByCon2 = null;
    for (Foo foo : bar) {
        if (conditional1 && conditional2) {
            return foo.getResult();
        }
        if (conditional1) {
            resultBycon1 = foo.getResult();
        }
        if (conditional2) {
            resultBycon2 = foo.getResult();
        }
    }
    return resultByCon1 != null ? resultByCon1
            : (resultByCon2 != null ? resultByCon2 : bar.get(0).getResult());

Upvotes: 2

Views: 149

Answers (2)

shmosel
shmosel

Reputation: 50716

Here's a solution that could be considered more elegant, but it requires a full pass for each condition. That is, it will return as soon as it finds an element matched by a condition, but it only evaluates one condition per pass (to preserve condition precedence). If you're dealing with a small list, you may be willing to take the hit:

List<Predicate<Foo>> conditions = Arrays.asList(
        foo -> conditional1 && conditional2,
        foo -> conditional1,
        foo -> conditional2,
        foo -> true
);

return conditions.stream()
        .map(condition -> bar.stream().filter(condition))
        .map(Stream::findFirst)
        .filter(Optional::isPresent)
        .findFirst()
        .map(Optional::get)
        .map(Foo::getResult)
        .get();

Upvotes: 1

Eran
Eran

Reputation: 393811

Here's one way, though I'm not sure how "nice" it is:

Integer[] resultByCon = new Integer[2];
return bar.stream()
          .filter (f -> {
                          if (conditional1 && conditional2) {
                              return true;
                          }
                          if (conditional1) {
                              resultBycon[0] = foo.getResult();
                          }
                          if (conditional2) {
                              resultBycon[1] = foo.getResult();
                          }
                          return false;
                        })
          .map(Foo::getResult)
          .findFirst()
          .orElseGet (() -> resultByCon[0] != null ? 
                      resultByCon[0] : 
                      (resultByCon[1] != null ? resultByCon[1] : bar.get(0).getResult()));

It contains all the logic in a single Stream pipeline, but it's probably less readable than your original code.

You may be able to do better using reduce().

Upvotes: 1

Related Questions