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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2768054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 12:37:16  来源:igfitidea点击:

How to get the first non-null value in Java?

javacoalesce

提问by froadie

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

是否有与 SQLCOALESCE函数等效的 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:

我想无论如何都将返回的第一个非NULL值的语句ab以及c-在这种情况下,它会返回b,或4.4。(类似于 sql 方法 - return COALESCE(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.

但我想知道是否有任何内置的、被接受的函数来完成这个。

采纳答案by les2

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

回答by Eric

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

回答by Eric

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

回答by Dave

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

如果只有两个变量要检查并且您使用的是番石榴,则可以使用MoreObjects.firstNonNull(T first, T second)

回答by Franta

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

应该使用,但在编译成字节码之前应该有一个预处理器,它可以找到这个“coalesce 函数”的用法并将其替换为类似的结构

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 中实现真正的合并!包括关键特性:仅在需要时才计算特定表达式——如果前面的表达式不为空,则不计算后面的表达式(不调用方法,不进行计算或磁盘/网络操作)。

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的文章:coalesce – hledáme neNULLové hodnoty–(用捷克语写的,但我希望代码示例对每个人都能理解)。

回答by Jamol

With Guava you can do:

使用番石榴,您可以:

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

which doesn't throw NPE if both aand bare null.

它不会抛出NPE如果两个abnull

EDIT: I was wrong, it does throw NPE. The correct way as commented by Michal ?izmaziais:

编辑:我错了,它确实抛出了 NPE。Michal ?izmazia评论的正确方法是:

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

回答by Christian Ullenboom

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.

如果导入 static Optional 表达式还不错。

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

不幸的是,使用 Optional 方法无法处理“多个变量”的情况。相反,您可以使用:

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

回答by Mario Rossi

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

只是为了完整性,“几个变量”的情况确实是可能的,尽管根本不优雅。例如,对于变量op以及q

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

Please note the use of orElseGet()attending to the case that o, p, and qare 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])

在最一般的情况下 coalesce(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]很可能已经是 类型Optional<String>,而不是简单的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 qshould be of type Supplier<String>like in:

此外,如果您也正在转向功能声明式风格,o, p, 和q应该是这样的类型Supplier<String>

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 coalescereduces simply to o.get().

然后整体coalesce简化为o.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()会返回Optional<Integer>

And then the coalescebecomes effectiveAge.get()or simply effectiveAgeif we are happy with a Supplier<Integer>.

然后coalesce变成effectiveAge.get()或者干脆effectiveAge如果我们很高兴能与一个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<T>调用Supplier<T>一次但懒惰的类,以及Optional<T>(即Optional<T>-Optional<T>运算符,甚至Supplier<Optional<T>>)的定义的一致性。

回答by Lonnie

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 方便地允许空条目,并且无论要考虑的对象数量如何,该表达式都是一致的。(在这种形式中,所有被考虑的对象都需要是相同的类型。)