If, Elseif and Else with Java 8

Asked

Viewed 1,055 times

5

I would like to build a method using Java 8, replacing the conditional IF, ELSE-IF and ELSE. For this, I built a sequence of code, I do not know if it is ideal and would like to hear better opinions or solutions.

public static void main(String[] args) {
    String a = " A ";
    String b = " B ";
    String c = " C ";
    String d = null;


    String teste = Optional.ofNullable(d)
            .map(String::trim)
            .orElseGet(() -> Optional.ofNullable(a)
                    .map(String::trim)
                    .orElseGet(() -> Optional.ofNullable(b)
                            .map(String::trim)
                            .orElseGet(() -> Optional.ofNullable(c)
                                    .map(String::trim)
                                    .orElse(""))));

    System.out.println(teste);
}

For didactic purposes, I used Strings as examples, BUT what if for example we had the following case: use a method "private String returns Search(String regex)". If regex finds something, it returns the String. If it returns NULL, I call the method again with another regex. And so on until the regex are finished and return by default the empty value ("")

Following example:

public static void main(String[] args) {
    String regexA = "A";
    String regexB = "B";
    String regexC = "C";

    Pattern patternA = Pattern.compile(regexA);
    Pattern patternB = Pattern.compile(regexB);
    Pattern patternC = Pattern.compile(regexC);

    String valor = " C ";


    String teste = Optional.ofNullable(valor)
            .map(str -> retornaBusca(str, patternA))
            .orElseGet(() -> Optional.ofNullable(valor)
                    .map(str -> retornaBusca(str, patternB))
                    .orElseGet(() -> Optional.ofNullable(valor)
                            .map(str -> retornaBusca(str, patternC))
                            .orElse("")));

    System.out.println(teste);
}

private static String retornaBusca(String str, Pattern regex) {
    return Optional.ofNullable(str)
            .map(regex::matcher)
            .filter(Matcher::find)
            .map(Matcher::group)
            .map(String::trim)
            .orElse(null);
}
  • The result of this System.out.println(test) will be that string?

  • Yes. Since d is null, it takes the value of a. If a is null, it takes the value of b. And so on. If it hits C and it’s null, it’s empty anyway. But the idea would be to replace the Strings with methods that return Strings if found from a regex or null if they do not find.

  • I edited my answer.

2 answers

8


The problem is that you are not using Streams, just a lot of Optionals. The way you did, the code is tied to the fact that it has exactly four variables, not just any number.

Try it like this:

import java.util.Arrays;
import java.util.Optional;

public class TesteOptional {
    public static void main(String[] args) {
        String a = " A ";
        String b = " B ";
        String c = " C ";
        String d = null;

        String teste = Arrays.asList(a, b, c, d)
                .stream()
                .map(Optional::ofNullable)
                .filter(Optional::isPresent)
                .map(Optional::orElseThrow)
                .map(String::trim)
                .findFirst()
                .orElse("");

        System.out.println(teste);
    }
}

Or if you prefer something simpler and faster, but less purist:

import java.util.Arrays;
import java.util.Optional;

public class TesteOptional {
    public static void main(String[] args) {
        String a = " A ";
        String b = " B ";
        String c = " C ";
        String d = null;

        String teste = Arrays.asList(a, b, c, d)
                .stream()
                .filter(x -> x != null)
                .map(String::trim)
                .findFirst()
                .orElse("");

        System.out.println(teste);
    }
}

Considering the issue of the question, I’ve come to this:

import java.util.Arrays;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TesteOptional2 {
    public static void main(String[] args) {
        Pattern a = Pattern.compile(" A ");
        Pattern b = Pattern.compile(" B ");
        Pattern c = Pattern.compile(" C ");

        String valor = " C ";

        String teste = Arrays.asList(a, b, c)
                .stream()
                .map(p -> retornaBusca(valor, p))
                .filter(Optional::isPresent)
                .map(Optional::orElseThrow)
                .findFirst()
                .orElse("");

        System.out.println(teste);
    }

    private static Optional<String> retornaBusca(String str, Pattern regex) {
        return Optional
                .ofNullable(str)
                .map(regex::matcher)
                .filter(Matcher::find)
                .map(Matcher::group)
                .map(String::trim);
    }
}

Note that in the above example, the parameter regex of retornaBusca can’t be null. I’m not sure I understand what you want, but I think that’s it.

  • Perfect, solves the situation. But what if I wanted to replace the Strings with methods that return Strings (which can return value or empty). I’ll give you an example closer to what I’m using: I call the "private String Returns" method. If regex finds something, it returns String. If it returns NULL, I call the method again with another regex. And so it goes until you finish the regex and return by default the empty value (""). If you need something more concrete I edit the question with an addendum.

  • @Gustavobatista I think it’s best to edit the question.

3

A for simple solve your problem:

class Main {

  public static void main(String[] args) {
    String result = findMatchingRegex(Arrays.asList(
        () -> testRegex(null),
        () -> testRegex(" A "),
        () -> testRegex(" B "),
        () -> testRegex(" C ")
    ));

    System.out.println(result);
  }

  public static String findMatchingRegex(List<Supplier<String>> suppliers) {
    for (Supplier<String> supplier : suppliers) {
      String value = supplier.get();
      if(value != null) {
        return value.trim();
      }
    }
    return "";
  }

  public static String testRegex(String input) {
    return input;
  }
}

But if you want to work with streams (Borrowing from @Victor Stafusa):

public static String findMatchingRegex(List<Supplier<String>> suppliers) {
  return suppliers.stream()
      .map(Supplier::get)
      .filter(Objects::nonNull)
      .findFirst()
      .map(String::trim)
      .orElse("");
}
  • Legal. Just one question: why use Supplier?

  • 1

    @Gustavobatista Why this way the tests are Lazy, as well as the orElseGet of Optional. If a test succeeds, the following tests need not be run.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.