176

SQLのCOALESCE機能に相当するJavaはありますか? つまり、いくつかの変数の最初の非 null 値を返す方法はありますか?

例えば

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

ab、およびの最初の非ヌル値を返すステートメントを何らかの方法で作成したいと考えています。cこの場合、b、または 4.4 を返します。(SQL メソッドのようなもの - return COALESCE(a,b,c))。次のような方法で明示的に実行できることを知っています。

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

しかし、これを達成するための組み込みの受け入れられた機能があるかどうか疑問に思いました。

4

13 に答える 13

260

アパッチ・コモンズ Lang 3

ObjectUtils.firstNonNull(T...)

Java 8 ストリーム

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

于 2013-09-11T12:51:47.723 に答える
124

いいえ、ありません。

あなたが得ることができる最も近いものは次のとおりです。

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

効率的な理由から、次のように一般的なケースを処理できます。

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 ...
}
于 2010-05-04T18:47:31.573 に答える
61

チェックする変数が 2 つしかなく、Guava を使用している場合は、MoreObjects.firstNonNull(T first, T second)を使用できます。

于 2011-07-18T19:48:35.547 に答える
57

テストする参照が 2 つしかなく、Java 8 を使用している場合は、次を使用できます。

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

static 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
于 2015-02-03T18:36:39.843 に答える
24

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);
}
于 2010-05-04T19:04:47.233 に答える
11

この状況では、何らかのプリプロセッサが必要です。最初の非 null 値を選択する関数 (静的メソッド) を作成すると、すべての項目が評価されるためです。一部のアイテムがメソッド呼び出しである場合は問題です (時間のかかるメソッド呼び出しである可能性があります)。また、このメソッドは、それらの前の項目が null でない場合でも呼び出されます。

このようないくつかの機能

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

を使用する必要がありますが、バイトコードにコンパイルする前に、この「合体機能」の使用法を見つけて、次のような構造に置き換えるプリプロセッサが必要です。

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

2014 年 9 月 2 日更新:

Java 8 と Lambdas のおかげで、Java で真の合体ができる可能性があります! 重要な機能が含まれています: 特定の式は必要な場合にのみ評価されます。前の式が null でない場合、次の式は評価されません (メソッドは呼び出されず、計算またはディスク/ネットワーク操作は実行されません)。

Java 8: 合体 - hledáme neNULLové hodnoty -に関する記事を書きました(チェコ語で書かれていますが、コード例がすべての人に理解できることを願っています)。

于 2012-02-19T18:45:24.863 に答える
6

これを試すことができます:

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

この回答をもとに

于 2018-01-10T17:28:40.577 に答える
4

完全を期すために、「いくつかの変数」のケースは確かに可能ですが、まったくエレガントではありません。たとえば、変数op、およびの場合q:

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

、、およびが変数ではなく、コストがかかるか、または望ましくない副作用を伴う式orElseGet()である場合に注意してください。opq

最も一般的なケースでは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

これにより、過度に長い式が生成される可能性があります。ただし、 のない世界に移動しようとしている場合は、単に ではなくnullv[i]すでに のタイプになっている可能性が最も高いです。この場合、Optional<String>String

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

または式の場合:

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

さらに、機能宣言型スタイルにも移行する場合、op、およびは次のような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 ) ;

そして、全体coalesceは単純に に還元されo.get()ます。

より具体的な例:

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()、そして当然のことながら、ageFromInput()すでに を返します。Optional<Integer>

そして、私たちが a に満足している場合、またはにcoalesceなります。effectiveAge.get()effectiveAgeSupplier<Integer>

私見ですが、Java 8 では、このように構造化されたコードがますます多く見られます。これは、特により複雑な場合に、非常に自明であると同時に効率的であるためです。

私は一度だけLazy<T>a を呼び出すクラスを見逃していますが、怠惰であり、 (つまり、演算子、または さえも) の定義の一貫性があります。Supplier<T>Optional<T>Optional<T>Optional<T>Supplier<Optional<T>>

于 2015-03-18T16:45:37.147 に答える
-2
Object coalesce(Object... objects)
{
    for(Object o : object)
        if(o != null)
            return o;
    return null;
}
于 2010-05-04T18:47:58.000 に答える