How to get the first non-null value in Java?
是否有SQL的等效SQL的
例如
我想以某种方式有一个语句将返回
1 | return a != null ? a : (b != null ? b : c) |
但我想知道是否有任何内置的,可接受的功能来实现这一目标。
Apache Commons Lang 3
Java 8 Stream
不,没有。
你最接近的是:
1 2 3 4 | public static < T > T coalesce(T ...items) { for(T i : items) if(i != null) return i; return null; } |
出于有效的原因,您可以按如下方式处理常见情况:
1 2 3 4 5 6 7 8 9 | public static < T > T coalesce(T a, T b) { return a == null ? b : a; } public static < T > T coalesce(T a, T b, T c) { return a != null ? a : (b != null ? b : c); } public static < T > T coalesce(T a, T b, T c, T d) { return ... } |
如果只检查两个变量并且您正在使用Guava,则可以使用MoreObjects.firstNonNull(T first,T second)。
如果只有两个参考测试,并且您使用的是Java 8,则可以使用
1 2 3 4 |
如果导入静态可选,表达式也不错。
不幸的是,使用Optional-method无法使用"几个变量"。相反,你可以使用:
1 2 3 4 5 6 |
继LES2的答案之后,您可以通过调用重载函数来消除高效版本中的一些重复:
1 2 3 4 5 6 7 8 9 10 11 12 | public static < T > T coalesce(T a, T b) { return a != null ? a : b; } public static < T > T coalesce(T a, T b, T c) { return a != null ? a : coalesce(b,c); } public static < T > T coalesce(T a, T b, T c, T d) { return a != null ? a : coalesce(b,c,d); } public static < T > T coalesce(T a, T b, T c, T d, T e) { return a != null ? a : coalesce(b,c,d,e); } |
这种情况需要一些预处理器。因为如果你编写一个函数(静态方法)来选择第一个非空值,它会评估所有项目。如果某些项是方法调用(可能是时间昂贵的方法调用),则会出现问题。即使它们之前的任何项不为null,也会调用此方法。
有些功能就是这样
1 | public static < T > T coalesce(T ...items) … |
应该使用但在编译成字节代码之前应该有一个预处理器,它可以找到这个?coalesce函数的用法"并用类似的构造替换它
1 | a != null ? a : (b != null ? b : c) |
更新2014-09-02:
感谢Java 8和Lambdas,有可能在Java中实现真正的合并!包括关键特性:特殊表达式仅在需要时进行评估 - 如果前一个不为空,则不评估后续的(不调用方法,不进行计算或磁盘/网络操作)。
我写了一篇关于它的文章Java 8:coalesce - hledámeneNULLovéhodnoty - (用捷克语编写,但我希望代码示例对每个人都是可以理解的)。
使用番石榴,您可以:
1 | Optional.fromNullable(a).or(b); |
如果
编辑:我错了,它确实抛出了NPE。 Michal?izmazia评论的正确方法是:
1 | Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull(); |
仅仅为了完整性,"几个变量"的情况确实是可能的,尽管根本不是优雅的。例如,对于变量
1 | Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) ) |
请注意使用
在最一般的情况下
1 2 | coalesce-expression(i) == e[i] when i = N coalesce-expression(i) == Optional.ofNullable( e[i] ).orElseGet(()-> coalesce-expression(i+1) ) when i < N |
这可能会生成过长的表达式。但是,如果我们试图移动到没有
1 | result= o.orElse(p.orElse(q.get())) ; |
或者在表达式的情况下:
1 | result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ; |
此外,如果您还要转换为函数声明式样式,
1 2 3 | Supplier<String> q= ()-> q-expr ; Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ; Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ; |
然后整个
有关更具体的示例:
1 2 3 4 | Supplier<Integer> hardcodedDefaultAge= ()-> 99 ; Supplier<Integer> defaultAge= ()-> defaultAgeFromDatabase().orElseGet( hardcodedDefaultAge ) ; Supplier<Integer> ageInStore= ()-> ageFromDatabase(memberId).orElseGet( defaultAge ) ; Supplier<Integer> effectiveAge= ()-> ageFromInput().orElseGet( ageInStore ) ; |
如果我们对
恕我直言,使用Java 8,我们将看到越来越多的代码结构,因为它同时具有极强的自我解释性和高效性,尤其是在更复杂的情况下。
我确实错过了一个
你可以试试这个:
1 2 3 | public static < T > T coalesce(T... t) { return Stream.of(t).filter(Objects::nonNull).findFirst().orElse(null); } |
基于此回复
当你想避免评估一些昂贵的方法时,如何使用供应商?
像这样:
1 2 3 4 5 6 7 8 | public static < T > T coalesce(Supplier< T >... items) { for (Supplier< T > item : items) { T value = item.get(); if (value != null) { return value; } return null; } |
然后像这样使用它:
1 |
您还可以使用重载方法来调用具有两个,三个或四个参数的调用。
此外,您还可以使用以下类似的流:
1 2 3 | public static < T > T coalesce2(Supplier< T >... s) { return Arrays.stream(s).map(Supplier::get).filter(Objects::nonNull).findFirst().orElse(null); } |
怎么样:
1 2 3 4 | firstNonNull = FluentIterable.from( Lists.newArrayList( a, b, c, ... ) ) .firstMatch( Predicates.notNull() ) .or( someKnownNonNullDefault ); |
Java ArrayList可以方便地允许空条目,并且无论要考虑的对象数量如何,此表达式都是一致的。 (在这种形式下,所有考虑的对象必须属于同一类型。)
1 2 3 4 5 6 7 |