web-dev-qa-db-ja.com

Java If Elseステートメントの短縮形

Nullをチェックするメソッドがあります。メソッドの行数を減らす方法はありますか?現在、コードは「ダーティ」に見えます。

private int similarityCount (String one, String two) {

    if (one == null && two == null) {
        return 1;
    } else if (one == null && two != null) {
        return 2;
    } else if (one != null && two == null) {
        return 3;
    } else {
        if(isMatch(one, two))
             return 4;
        return 5;
    }

}
28
userit1985
private int similarityCount (String one, String two) {

    if (one == null && two == null) {
        return 1;
    } 

    if (one == null) {
        return 2;
    } 

    if (two == null) {
        return 3;
    } 

    if (isMatch(one, two)) {
        return 4;
    }
    return 5;
}
61
Manh Le

私はそのような場合にネストされた条件を好む:

private int similarityCount (String one, String two) {
    if (one==null) {
        if (two==null) {
            return 1;
        } else {
            return 2;
        }
    } else {
        if (two==null) {
            return 3;
        } else {
            return isMatch(one, two) ? 4 : 5;
        }
    }
}

もちろん、より多くの三項条件演算子を使用することで、より短いバージョンを実現できます。

private int similarityCount (String one, String two) {  
    if (one==null) {
        return (two==null) ? 1 : 2;
    } else {
        return (two==null) ? 3 : isMatch(one, two) ? 4 : 5;
    }
}

またはさらに(今ではこれは読みにくくなっています):

private int similarityCount (String one, String two) {  
    return (one==null) ? ((two==null) ? 1 : 2) : ((two==null) ? 3 : isMatch(one, two) ? 4 : 5);
}
33
Eran

関数の実際の目的は非nullオブジェクトを一致させることで処理することであるため、最初にガードステートメントですべてのnullチェックを処理します。

次に、nullである引数がないことを確認したら、実際のロジックを処理できます。

private int similarityCount(String a, String b) {
    if (a == null || b == null) {
        return a == b ? 1 : a == null ? 2 : 3;
    }

    return isMatch(a, b) ? 4 : 5;
}

これは、他のオプションよりも簡潔で読みやすいです。

ただし、real関数は通常、このような数値コードを返しません。問題を例示するためにメソッドが単純化されていない限り、ロジックを再考し、代わりに次のような内容を書くことを強くお勧めします。

private boolean similarityCount(String a, String b) {
    if (a == null || b == null) {
        throw new NullPointerException();
    }

    return isMatch(a, b);
}

または:

private boolean similarityCount(String a, String b) {
    if (a == null) {
        throw new IllegalArgumentException("a");
    }
    if (b == null) {
        throw new IllegalArgumentException("b");
    }

    return isMatch(a, b);
}

これらのアプローチはより一般的です。反対に、例外をトリガーする場合があります。 Java 8:でJava.util.Optional<Boolean>を返すことでこれを回避できます:

private Optional<Boolean> similarityCount(String a, String b) {
    if (a == null || b == null) {
        return Optional.empty();
    }

    return Optional.of(isMatch(a, b));
}

一見すると、これはnullを返すよりも良くないように思えるかもしれませんが、 オプションは実際にははるかに優れています です。

25
Konrad Rudolph

コードは私にとって十分に明確に見えます。ネスト演算子と三項演算子を使用して短くすることができます。

if(one==null) {
    return two==null ? 1 : 2;
}
if(two==null) {
    return 3;
} 
return isMatch(one,two) ? 4 : 5;
9
default locale

Java条件演算子を使用して1行で実行できます。

return (one==null?(two==null?1:2):(two==null?3:(isMatch(one,two)?4:5)));
5
SachinSarawgi

can擬似ルックアップテーブルを作成します。一部の人々はネストされた三項演算子に眉をひそめ、読みやすさのために空白に非常に依存していますが、それはcan条件付き復帰のための非常に読みやすいアプローチです:

private int similarityCount (String one, String two) {
    return (one == null && two == null) ? 1
         : (one == null && two != null) ? 2
         : (one != null && two == null) ? 3
         : isMatch(one, two)            ? 4
         :                                5;
}
4
Dancrumb

表現が好きです。

private static int similarityCount (String one, String two) {    
    return one == null ? 
        similarityCountByTwoOnly(two) : 
        two == null ? 3 : (isMatch(one, two) ? 4 : 5)
    ;
}

private static int similarityCountByTwoOnly(String two) {
    return two == null ? 1 : 2;
}

余談ですが、おそらくあなたがこれをしている理由に挑戦するでしょう。返された整数を評価し、それに基づいてロジックを分岐した後、返された整数に対して何らかのチェックを行うと思います。その場合は、メソッドのユーザーが整数の値に暗黙的に含まれるコントラクトを理解する必要がある場合、nullの可読性が低いチェックを行いました。

また、文字列がnullの可能性があるときに等しいかどうかを確認する必要がある場合の簡単な解決策を次に示します。

boolean same = one == null ? two == null : one.equals(two);
1
Erik Madsen

どちらもnullでない場合、この場合は 'if'ステートメントを1つしか実行しないため、これはわずかに高速になります。

private int similarityCount (String one, String two) {

    if (one == null || two == null) {  // Something is null
        if (two != null) { // Only one is null
            return 2;
        }

        if (one != null) { // Only two is null
            return 3;
        }

        return 1; // Both must be null
    } 

    return isMatch(one, two) ? 4 : 5;
}
0
user7507190

笑...プログラミングは美人コンテストではありません。あなたのコード

if (one == null && two == null) {
        return 1;
} else if (one == null && two != null) {
        return 2;
    } else if (one != null && two == null) {
        return 3;
    } else {
        if(isMatch(one, two))
             return 4;
        return 5;
    }

汚れていませんが、素人にも専門家にも十分な美しさです。次のコーディングについてどう思いますか

return one == null && two == null ? 1:
       one == null && two != null ? 2:
       one != null && two == null ? 3:
       isMatch(one, two) ? 4 : 5;

すごいですね。まあ、素人にとっては「ブードゥー教」、「専門家」にとっては...「味」、「政治」、「宗教」について議論すべきではありません。しかし、パフォーマンスの観点からはそうです:

  • 最初のバージョンはより高速です
  • 2番目のバージョンは不器用(または低速)です。

なぜ? 「javac -g:none Test5 * .Java」をコンパイルして、生成されたバイトコードを比較します。私はそれをしました、そして結果はここにあります:

最初のバージョン:

public class Test5 {
    public static void main(String[] args) {
        String one = "1";
        String two = "2";
        System.out.println(check(one, two));
    }
    private static int check(String one, String two) {
        if (one == null && two == null) {
                return 1;
        } else if (one == null && two != null) {
                return 2;
            } else if (one != null && two == null) {
                return 3;
            } else {
                if(isMatch(one, two))
                     return 4;
                return 5;
            }
    }
    public static boolean isMatch(String a, String b) {
        return true;
    }
}

570バイト生成

2番目のバージョン:

public class Test5a {
    public static void main(String[] args) {
        String one = "1";
        String two = "2";
        System.out.println(check(one, two));
    }
    private static int check(String one, String two) {
        return one == null && two == null ? 1:
               one == null && two != null ? 2:
               one != null && two == null ? 3:
               isMatch(one, two) ? 4 : 5;
    }
    public static boolean isMatch(String a, String b) {
        return true;
    }
}

581バイトを生成します

11バイトを処理する必要があり、時間がかかることは明らかです...アプリが持つ「過剰な」コードほど、パフォーマンスが低下します。

0
Voodoo

IFステートメントを削除するのは楽しいことです。これを行う1つの方法は、マップを使用することです。 isMatchの呼び出しが原因でこのケースに正確には適合しませんが、ifimilarityCountメソッドの本文を1つのIFを持つ単一行にカットする代替手段として提供します

次のコードには2つのIFがあります。 GetOrDefaultが2番目の引数を評価しなかった場合、1つに減らすことができます。残念なことに、isMatch内のnullチェックが必要です。

必要に応じて、これをさらに進めることができます。たとえば、isMatchはブール値ではなく4または5を返すことができます。これにより、さらに簡単になります。

import com.google.common.collect.ImmutableMap;
import org.Apache.commons.lang3.builder.EqualsBuilder;
import org.Apache.commons.lang3.builder.HashCodeBuilder;

import Java.util.Map;

public class SimilarityCount {

    private Map<SimilarityCountKey, Integer> rtn = ImmutableMap.of(new SimilarityCountKey(null, null), 1, new SimilarityCountKey(null, ""), 2, new SimilarityCountKey("", null), 3);

    public int similarityCount(String one, String two) {
        return rtn.getOrDefault(new SimilarityCountKey(one, two), isMatch(one, two) ? 4 : 5);
    }

    private boolean isMatch(String one, String two) {
        if (one == null || two == null) {
            return false;
        }
        return one.equals(two);
    }

    private class SimilarityCountKey {
        private final boolean one;
        private final boolean two;

        public SimilarityCountKey(String one, String two) {
            this.one = one == null;
            this.two = two == null;
        }

        @Override
        public boolean equals(Object obj) {
            return EqualsBuilder.reflectionEquals(this, obj);
        }

        @Override
        public int hashCode() {
            return HashCodeBuilder.reflectionHashCode(this);
        }
    }
}

他の誰かが別のソリューションでクラックを空想した場合、ここであなたが始めるのに役立ついくつかのテストがあります

 import org.junit.Assert;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;

public class SimilarityCountTest {

    @Test
    public void one(){
        Assert.assertThat(new SimilarityCount().similarityCount(null,null), is(1));
    }

    @Test
    public void two(){
        Assert.assertThat(new SimilarityCount().similarityCount(null,""), is(2));
    }

    @Test
    public void three(){
        Assert.assertThat(new SimilarityCount().similarityCount("",null), is(3));
    }

    @Test
    public void four(){
        Assert.assertThat(new SimilarityCount().similarityCount("",""), is(4));
    }

    @Test
    public void five(){
        Assert.assertThat(new SimilarityCount().similarityCount("a","b"), is(5));
    }

}
0
Mark Chorley