Return first non-null value

前端 未结 8 1981
情歌与酒
情歌与酒 2020-12-14 07:17

I have a number of functions:

String first(){}
String second(){}
...
String default(){}

Each can return a null value, except the default. <

相关标签:
8条回答
  • 2020-12-14 08:08

    If you want to package it up into a utility method, you'll have to wrap each function up into something that defers execution. Perhaps something like this:

    public interface Wrapper<T> {
        T call();
    }
    
    public static <T> T firstNonNull(Wrapper<T> defaultFunction, Wrapper<T>... funcs) {
        T val;
        for (Wrapper<T> func : funcs) {
           if ((val = func.call()) != null) {
               return val;
           }
        }
        return defaultFunction.call();
    }
    

    You could use java.util.concurrent.Callable instead of defining your own Wrapper class, but then you'd have to deal with the exception that Callable.call() is declared to throw.

    This can then be called with:

    String value = firstNonNull(
        new Wrapper<>() { @Override public String call() { return defaultFunc(); },
        new Wrapper<>() { @Override public String call() { return first(); },
        new Wrapper<>() { @Override public String call() { return second(); },
        ...
    );
    

    In Java 8, as @dorukayhan points out, you can dispense with defining your own Wrapper class and just use the Supplier interface. Also, the call can be done much more cleanly with lambdas:

    String value = firstNonNull(
        () -> defaultFunc(),
        () -> first(),
        () -> second(),
        ...
    );
    

    You can also (as @Oliver Charlesworth suggests) use method references as shorthand for the lambda expressions:

    String value = firstNonNull(
        MyClass::defaultFunc,
        MyClass::first,
        MyClass::second,
        ...
    );
    

    I'm of two minds as to which is more readable.

    Alternatively, you can use one of the streaming solutions that many other answers have proposed.

    0 讨论(0)
  • 2020-12-14 08:10

    Just make a class with one function like this:

    class ValueCollector {
      String value;
      boolean v(String val) { this.value = val; return val == null; }
    }
    
    ValueCollector c = new ValueCollector();
    if c.v(first()) || c.v(second()) ...
    return c.value;
    
    0 讨论(0)
提交回复
热议问题