如何在Java中获得第一个非空值?

时间:2020-12-06 11:46:39

Is there a Java equivalent of SQL's COALESCE function? That is, is there any way to return the first non-null value of several variables?

是否存在与SQL合并函数相同的Java ?也就是说,是否有方法返回多个变量的第一个非空值?

e.g.

如。

Double a = null;
Double b = 4.4;
Double c = null;

I want to somehow have a statement that will return the first non-null value of a, b, and c - in this case, it would return b, or 4.4. (Something like the sql method - return COALESCE(a,b,c)). I know that I can do it explicitly with something like:

我想要有一个声明,它将返回a, b和c的第一个非空值,在这个例子中,它会返回b,或者是4.4。(类似于sql方法-返回合并(a,b,c))。我知道我可以用类似的方法来做

return a != null ? a : (b != null ? b : c)

But I wondered if there was any built-in, accepted function to accomplish this.

但是我想知道是否有内置的,被接受的功能来完成这个。

12 个解决方案

#1


88  

No, there isn't.

不,没有。

The closest you can get is:

你能得到的最接近的是:

public static <T> T coalesce(T ...items) {
    for(T i : items) if(i != null) return i;
    return null;
}

For efficient reasons, you can handle the common cases as follows:

由于有效的原因,你可以处理常见的情况如下:

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 ...
}

#2


100  

Apache Commons Lang 3

Apache Commons Lang 3

ObjectUtils.firstNonNull(T...)

ObjectUtils.firstNonNull(T…)

Java 8 Stream

Java 8流

Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)

Stream.of(T…).filter(对象::null).findFirst().orElse(空)

#3


50  

If there are only two variables to check and you're using Guava, you can use MoreObjects.firstNonNull(T first, T second).

如果只有两个变量需要检查,并且使用了Guava,那么可以使用更多的对象。firstNonNull(T,T秒)。

#4


30  

If there are only two references to test and you are using Java 8, you could use

如果只有两个测试引用,而您使用的是Java 8,则可以使用。

Object o = null;
Object p = "p";
Object r = Optional.ofNullable( o ).orElse( p );
System.out.println( r );   // p

If you import static Optional the expression is not too bad.

如果导入静态可选,表达式也不太坏。

Unfortunately your case with "several variables" is not possible with an Optional-method. Instead you could use:

不幸的是,您的“几个变量”的情况是不可能的,用一个optionalmethod。相反,您可以使用:

Object o = null;
Object p = null;
Object q = "p";

Optional<Object> r = Stream.of( o, p, q ).filter( Objects::nonNull ).findFirst();
System.out.println( r.orElse(null) );   // p

#5


23  

Following on from LES2's answer, you can eliminate some repetition in the efficient version, by calling the overloaded function:

根据LES2的答案,您可以通过调用重载函数来消除一些重复的有效版本:

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);
}

#6


7  

This situation calls for some preprocessor. Because if you write a function (static method) which picks the first not null value, it evaluates all items. It is problem if some items are method calls (may be time expensive method calls). And this methods are called even if any item before them is not null.

这种情况需要一些预处理器。因为如果您编写一个函数(静态方法),它选择第一个非空值,它将对所有项进行评估。如果某些项是方法调用(可能是时间代价昂贵的方法调用),那么问题就出现了。这种方法被调用,即使在它们之前的任何项都不是空的。

Some function like this

这样的一个函数

public static <T> T coalesce(T ...items) …

should be used but before compiling into byte code there should be a preprocessor which find usages of this „coalesce function“ and replaces it with construction like

应该使用在编译成字节码之前应该有一个预处理器,找到这个„合并函数的用法”和取代它与建设

a != null ? a : (b != null ? b : c)

Update 2014-09-02:

更新2014-09-02:

Thanks to Java 8 and Lambdas there is possibility to have true coalesce in Java! Including the crucial feature: particular expressions are evaluated only when needed – if earlier one is not null, then following ones are not evaluated (methods are not called, computation or disk/network operations are not done).

感谢Java 8和Lambdas,在Java中有可能实现真正的合并!包括关键特性:只有在需要时才计算特定的表达式——如果前面的表达式不是null,那么下面的表达式就不会被评估(方法不被调用,计算或磁盘/网络操作没有完成)。

I wrote an article about it Java 8: coalesce – hledáme neNULLové hodnoty – (written in Czech, but I hope that code examples are understandable for everyone).

我写了一篇关于Java 8的文章:合并- hledame neNULLove hodnoty -(用捷克语写的,但我希望每个人都能理解代码示例)。

#7


5  

With Guava you can do:

你可以用番石榴做:

Optional.fromNullable(a).or(b);

which doesn't throw NPE if both a and b are null.

如果a和b都为空,它不会抛出NPE。

EDIT: I was wrong, it does throw NPE. The correct way as commented by Michal Čizmazia is:

编辑:我错了,它确实扔了NPE。说的正确方法米甲Čizmazia是:

Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull();

#8


3  

Just for completness, the "several variables" case is indeed possible, though not elegant at all. For example, for variables o, p, and q:

仅仅为了完全,“几个变量”的例子确实是可能的,尽管一点也不优雅。例如,对于变量o、p和q:

Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )

Please note the use of orElseGet() attending to the case that o, p, and q are not variables but expressions either expensive or with undesired side-effects.

请注意orElseGet()的使用,注意到o、p和q不是变量,但是表达式要么是昂贵的,要么是没有希望的副作用。

In the most general case coalesce(e[1],e[2],e[3],...,e[N])

在最普遍的情况下合并(e[1],e[2],e[3],…,e[N])

coalesce-expression(i) ==  e[i]  when i = N
coalesce-expression(i) ==  Optional.ofNullable( e[i] ).orElseGet(()-> coalesce-expression(i+1) )  when i < N

This can generate expressions excessively long. However, if we are trying to move to a world without null, then v[i] are most probably already of type Optional<String>, as opposed to simply String. In this case,

这可以生成非常长的表达式。但是,如果我们试图移动到一个没有null的世界,那么v[i]很可能已经是可选的 ,而不是简单的String。在这种情况下,

result= o.orElse(p.orElse(q.get())) ;

or in the case of expressions:

或者在表达的情况下:

result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;

Furthermore, if you are also moving to a functional-declarative style, o, p, and q should be of type Supplier<String> like in:

此外,如果您还在移动到功能声明式样式,o、p和q应该是类型供应商 ,如:

Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;

And then the whole coalesce reduces simply to o.get().

然后整个合并就变成了。get()。

For a more concrete example:

举一个更具体的例子:

Supplier<Integer> hardcodedDefaultAge= ()-> 99 ;
Supplier<Integer> defaultAge= ()-> defaultAgeFromDatabase().orElseGet( hardcodedDefaultAge ) ;
Supplier<Integer> ageInStore= ()-> ageFromDatabase(memberId).orElseGet( defaultAge ) ;
Supplier<Integer> effectiveAge= ()-> ageFromInput().orElseGet( ageInStore ) ;

defaultAgeFromDatabase(), ageFromDatabase(), and ageFromInput() would already return Optional<Integer>, naturally.

defaultAgeFromDatabase()、ageFromDatabase()和ageFromInput()将会自然返回可选的

And then the coalesce becomes effectiveAge.get() or simply effectiveAge if we are happy with a Supplier<Integer>.

如果我们对供应商 <整数> 表示满意,那么合并就会变得有效。

IMHO, with Java 8 we will see more and more code structured like this, as it's extremely self-explainatory and efficient at the same time, especially in more complex cases.

在Java 8中,我们将看到越来越多的代码是这样构建的,因为它是非常自我解释和高效的,特别是在更复杂的情况下。

I do miss a class Lazy<T> that invokes a Supplier<T> only one time, but lazily, as well as consistency in the definition of Optional<T> (i.e. Optional<T>-Optional<T> operators, or even Supplier<Optional<T>>).

我很容易忽略一个类的Lazy ,它只调用了一个供应商 ,但是延迟了,并且在可选 的定义中有一致性(例如,可选 -可选 操作符,甚至是供应商 <可选 >)。

#9


1  

How about using suppliers when you want to avoid evaluating some expensive method?

当你想避免评估一些昂贵的方法时,如何使用供应商?

Like this:

是这样的:

public static <T> T coalesce(Supplier<T>... items) {
for (Supplier<T> item : items) {
    T value = item.get();
    if (value != null) {
        return value;
    }
    return null;
}

And then using it like this:

然后像这样使用:

Double amount = coalesce(order::firstAmount, order::secondAmount, order::thirdAmount)

You can also use overloaded methods for the calls with two, three or four arguments.

您还可以使用两个、三或四个参数调用重载方法。

In addition, you could also use streams with something like this:

此外,您还可以使用这样的流:

public static <T> T coalesce2(Supplier<T>... s) {
    return Arrays.stream(s).map(Supplier::get).filter(Objects::nonNull).findFirst().orElse(null);
}

#10


0  

Object coalesce(Object... objects)
{
    for(Object o : object)
        if(o != null)
            return o;
    return null;
}

#11


0  

How about:

如何:

firstNonNull = FluentIterable.from(
    Lists.newArrayList( a, b, c, ... ) )
        .firstMatch( Predicates.notNull() )
            .or( someKnownNonNullDefault );

Java ArrayList conveniently allows null entries and this expression is consistent regardless of the number of objects to be considered. (In this form, all the objects considered need to be of the same type.)

Java ArrayList可以方便地允许空条目,无论需要考虑多少对象,这个表达式都是一致的。(在此表单中,所有被认为需要的对象都是相同类型的。)

#12


0  

You can try this:

你可以试试这个:

public static <T> T coalesce(T... t) {
    return Stream.of(t).filter(Objects::nonNull).findFirst().orElse(null);
}

Based on this response

在此基础上的反应

#1


88  

No, there isn't.

不,没有。

The closest you can get is:

你能得到的最接近的是:

public static <T> T coalesce(T ...items) {
    for(T i : items) if(i != null) return i;
    return null;
}

For efficient reasons, you can handle the common cases as follows:

由于有效的原因,你可以处理常见的情况如下:

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 ...
}

#2


100  

Apache Commons Lang 3

Apache Commons Lang 3

ObjectUtils.firstNonNull(T...)

ObjectUtils.firstNonNull(T…)

Java 8 Stream

Java 8流

Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)

Stream.of(T…).filter(对象::null).findFirst().orElse(空)

#3


50  

If there are only two variables to check and you're using Guava, you can use MoreObjects.firstNonNull(T first, T second).

如果只有两个变量需要检查,并且使用了Guava,那么可以使用更多的对象。firstNonNull(T,T秒)。

#4


30  

If there are only two references to test and you are using Java 8, you could use

如果只有两个测试引用,而您使用的是Java 8,则可以使用。

Object o = null;
Object p = "p";
Object r = Optional.ofNullable( o ).orElse( p );
System.out.println( r );   // p

If you import static Optional the expression is not too bad.

如果导入静态可选,表达式也不太坏。

Unfortunately your case with "several variables" is not possible with an Optional-method. Instead you could use:

不幸的是,您的“几个变量”的情况是不可能的,用一个optionalmethod。相反,您可以使用:

Object o = null;
Object p = null;
Object q = "p";

Optional<Object> r = Stream.of( o, p, q ).filter( Objects::nonNull ).findFirst();
System.out.println( r.orElse(null) );   // p

#5


23  

Following on from LES2's answer, you can eliminate some repetition in the efficient version, by calling the overloaded function:

根据LES2的答案,您可以通过调用重载函数来消除一些重复的有效版本:

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);
}

#6


7  

This situation calls for some preprocessor. Because if you write a function (static method) which picks the first not null value, it evaluates all items. It is problem if some items are method calls (may be time expensive method calls). And this methods are called even if any item before them is not null.

这种情况需要一些预处理器。因为如果您编写一个函数(静态方法),它选择第一个非空值,它将对所有项进行评估。如果某些项是方法调用(可能是时间代价昂贵的方法调用),那么问题就出现了。这种方法被调用,即使在它们之前的任何项都不是空的。

Some function like this

这样的一个函数

public static <T> T coalesce(T ...items) …

should be used but before compiling into byte code there should be a preprocessor which find usages of this „coalesce function“ and replaces it with construction like

应该使用在编译成字节码之前应该有一个预处理器,找到这个„合并函数的用法”和取代它与建设

a != null ? a : (b != null ? b : c)

Update 2014-09-02:

更新2014-09-02:

Thanks to Java 8 and Lambdas there is possibility to have true coalesce in Java! Including the crucial feature: particular expressions are evaluated only when needed – if earlier one is not null, then following ones are not evaluated (methods are not called, computation or disk/network operations are not done).

感谢Java 8和Lambdas,在Java中有可能实现真正的合并!包括关键特性:只有在需要时才计算特定的表达式——如果前面的表达式不是null,那么下面的表达式就不会被评估(方法不被调用,计算或磁盘/网络操作没有完成)。

I wrote an article about it Java 8: coalesce – hledáme neNULLové hodnoty – (written in Czech, but I hope that code examples are understandable for everyone).

我写了一篇关于Java 8的文章:合并- hledame neNULLove hodnoty -(用捷克语写的,但我希望每个人都能理解代码示例)。

#7


5  

With Guava you can do:

你可以用番石榴做:

Optional.fromNullable(a).or(b);

which doesn't throw NPE if both a and b are null.

如果a和b都为空,它不会抛出NPE。

EDIT: I was wrong, it does throw NPE. The correct way as commented by Michal Čizmazia is:

编辑:我错了,它确实扔了NPE。说的正确方法米甲Čizmazia是:

Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull();

#8


3  

Just for completness, the "several variables" case is indeed possible, though not elegant at all. For example, for variables o, p, and q:

仅仅为了完全,“几个变量”的例子确实是可能的,尽管一点也不优雅。例如,对于变量o、p和q:

Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )

Please note the use of orElseGet() attending to the case that o, p, and q are not variables but expressions either expensive or with undesired side-effects.

请注意orElseGet()的使用,注意到o、p和q不是变量,但是表达式要么是昂贵的,要么是没有希望的副作用。

In the most general case coalesce(e[1],e[2],e[3],...,e[N])

在最普遍的情况下合并(e[1],e[2],e[3],…,e[N])

coalesce-expression(i) ==  e[i]  when i = N
coalesce-expression(i) ==  Optional.ofNullable( e[i] ).orElseGet(()-> coalesce-expression(i+1) )  when i < N

This can generate expressions excessively long. However, if we are trying to move to a world without null, then v[i] are most probably already of type Optional<String>, as opposed to simply String. In this case,

这可以生成非常长的表达式。但是,如果我们试图移动到一个没有null的世界,那么v[i]很可能已经是可选的 ,而不是简单的String。在这种情况下,

result= o.orElse(p.orElse(q.get())) ;

or in the case of expressions:

或者在表达的情况下:

result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;

Furthermore, if you are also moving to a functional-declarative style, o, p, and q should be of type Supplier<String> like in:

此外,如果您还在移动到功能声明式样式,o、p和q应该是类型供应商 ,如:

Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;

And then the whole coalesce reduces simply to o.get().

然后整个合并就变成了。get()。

For a more concrete example:

举一个更具体的例子:

Supplier<Integer> hardcodedDefaultAge= ()-> 99 ;
Supplier<Integer> defaultAge= ()-> defaultAgeFromDatabase().orElseGet( hardcodedDefaultAge ) ;
Supplier<Integer> ageInStore= ()-> ageFromDatabase(memberId).orElseGet( defaultAge ) ;
Supplier<Integer> effectiveAge= ()-> ageFromInput().orElseGet( ageInStore ) ;

defaultAgeFromDatabase(), ageFromDatabase(), and ageFromInput() would already return Optional<Integer>, naturally.

defaultAgeFromDatabase()、ageFromDatabase()和ageFromInput()将会自然返回可选的

And then the coalesce becomes effectiveAge.get() or simply effectiveAge if we are happy with a Supplier<Integer>.

如果我们对供应商 <整数> 表示满意,那么合并就会变得有效。

IMHO, with Java 8 we will see more and more code structured like this, as it's extremely self-explainatory and efficient at the same time, especially in more complex cases.

在Java 8中,我们将看到越来越多的代码是这样构建的,因为它是非常自我解释和高效的,特别是在更复杂的情况下。

I do miss a class Lazy<T> that invokes a Supplier<T> only one time, but lazily, as well as consistency in the definition of Optional<T> (i.e. Optional<T>-Optional<T> operators, or even Supplier<Optional<T>>).

我很容易忽略一个类的Lazy ,它只调用了一个供应商 ,但是延迟了,并且在可选 的定义中有一致性(例如,可选 -可选 操作符,甚至是供应商 <可选 >)。

#9


1  

How about using suppliers when you want to avoid evaluating some expensive method?

当你想避免评估一些昂贵的方法时,如何使用供应商?

Like this:

是这样的:

public static <T> T coalesce(Supplier<T>... items) {
for (Supplier<T> item : items) {
    T value = item.get();
    if (value != null) {
        return value;
    }
    return null;
}

And then using it like this:

然后像这样使用:

Double amount = coalesce(order::firstAmount, order::secondAmount, order::thirdAmount)

You can also use overloaded methods for the calls with two, three or four arguments.

您还可以使用两个、三或四个参数调用重载方法。

In addition, you could also use streams with something like this:

此外,您还可以使用这样的流:

public static <T> T coalesce2(Supplier<T>... s) {
    return Arrays.stream(s).map(Supplier::get).filter(Objects::nonNull).findFirst().orElse(null);
}

#10


0  

Object coalesce(Object... objects)
{
    for(Object o : object)
        if(o != null)
            return o;
    return null;
}

#11


0  

How about:

如何:

firstNonNull = FluentIterable.from(
    Lists.newArrayList( a, b, c, ... ) )
        .firstMatch( Predicates.notNull() )
            .or( someKnownNonNullDefault );

Java ArrayList conveniently allows null entries and this expression is consistent regardless of the number of objects to be considered. (In this form, all the objects considered need to be of the same type.)

Java ArrayList可以方便地允许空条目,无论需要考虑多少对象,这个表达式都是一致的。(在此表单中,所有被认为需要的对象都是相同类型的。)

#12


0  

You can try this:

你可以试试这个:

public static <T> T coalesce(T... t) {
    return Stream.of(t).filter(Objects::nonNull).findFirst().orElse(null);
}

Based on this response

在此基础上的反应