Return first non-null value

前端 未结 8 1982
情歌与酒
情歌与酒 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 07:55

    String s = Stream.>of(this::first, this::second /*, ... */)
                     .map(Supplier::get)
                     .filter(Objects::nonNull)
                     .findFirst()
                     .orElseGet(this::defaultOne);
    

    It stops on the first non-null value or else sets the value which is returned from defaultOne. As long as you stay sequential, you are safe. Of course this requires Java 8 or later.

    The reason why it stops on the first occurrence of a non-null value is due how the Stream handles each step. The map is an intermediate operation, so is filter. The findFirst on the other side is a short-circuiting terminal operation. So it continues with the next element until one matches the filter. If no element matches an empty optional is returned and so the orElseGet-supplier is called.

    this::first, etc. are just method references. If they are static replace it with YourClassName::first, etc.

    Here is an example if the signature of your methods would differ:

    String s = Stream.>of(() -> first("takesOneArgument"),
                                           () -> second("takes", 3, "arguments")
                                       /*, ... */)
                     .map(Supplier::get)
                     .filter(Objects::nonNull)
                     .findFirst()
                     .orElseGet(this::defaultOne);
    

    Note that the Supplier is only evaluated when you call get on it. That way you get your lazy evaluation behaviour. The method-parameters within your supplier-lambda-expression must be final or effectively final.

提交回复
热议问题