3

How to replace the below code using Java 8 Optionals (Functional programming)?

ClassA classA = dbService.findByA(a);

if (classA == null) {
    classA = dbService.findByB(b);
}

if (classA == null) {
    throw new Exception();
}

return classA;

edit: Maybe if I will make findByA and findByB returning Optional will make my code cleaner using Functional programming?

0seNse0
  • 43
  • 5
  • 3
    A functional interface is an interface that contains only one abstract method. What exactly do you need to implement using the functional interface? – Staphy Joseph Nov 18 '19 at 12:37
  • I think you want a solution using the functional programming paradigm. – Jayesh Patel Nov 18 '19 at 12:38
  • Yes, maybe I was unclear. I want to make it with Optionals (Functional programming). – 0seNse0 Nov 18 '19 at 12:40
  • 1
    Make findByA return an Optional. If you can't do that, then don't touch anything in that code. Optional is not meant to replace null checks. https://stackoverflow.com/questions/52038417/should-optional-ofnullable-be-used-for-null-check – JB Nizet Nov 18 '19 at 12:42
  • throwing an exception is not a functional style/programing – Serhii Povísenko Nov 18 '19 at 12:43

3 Answers3

3
return Optional.ofNullable(Optional.ofNullable(dbService.findByA(a))
    .orElseGet(() -> dbService.findByB(b)))
    .orElseThrow(() -> new Exception());

Or, Java 9, a bit nicer:

Optional.ofNullable(dbService.findByA(a))
    .or(() -> Optional.ofNullable(dbService.findByB(b)))
    .orElseThrow(() -> new Exception());
Smutje
  • 17,733
  • 4
  • 24
  • 41
2

This would work

Optional.ofNullable(
    Optional.ofNullable(dbService.findByA(a))
            .orElseGet(() -> dbService.findByB(b))
).orElseThrow(Exception::new);

I don't think this is much nicer.

daniu
  • 14,137
  • 4
  • 32
  • 53
1

First, make your methods dbService.findByA and dbService.findByB return Optional. That's the basis. If you don't do that, you don't do "functional" programming.

Second, use Java 9+ (or better, the latest version).

Then simply use the following:

ClassA instance = dbService.findByA(a)
    .or(() -> dbService.findByB(b))
    .orElseThrow(Exception::new);

If you're stuck with Java 8, do the following:

ClassA instance = Optional.of(() -> dbService.findByA(a)) // Optional<Optional<ClassA>>
    .orElseGet(() -> dbService.findByB(b)) // Optional<ClassA>
    .orElseThrow(Exception::new);
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • I can make them returning Optional but I can't use Java 9+, can you help me how to write it in Java 8? – 0seNse0 Nov 18 '19 at 12:57
  • @0seNse0 I updated my answer. It's ugly and similar to the other answers. That's why I strongly recommend upgrading to Java 9 or higher. Java 8 is already 5.5 years old (and is not commercially supported anymore). That's a lot! You should really have a plan for upgrade. – Olivier Grégoire Nov 18 '19 at 13:07
  • @OlivierGrégoire Java 9/10 can't be download, only Java 11, and Java 8 is supported https://www.oracle.com/technetwork/java/java-se-support-roadmap.html – Ori Marko Nov 18 '19 at 13:47
  • @user7294900 My bad. I based myself on the Wikipedia article which apparently isn't up to date on that regards. Anyways, it's good to keep up with the ongoing developments and use later versions to not be left behind when Java 8 isn't supported anymore. – Olivier Grégoire Nov 18 '19 at 14:02