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;
}
}
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;
}
私はそのような場合にネストされた条件を好む:
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);
}
関数の実際の目的は非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
を返すよりも良くないように思えるかもしれませんが、 オプションは実際にははるかに優れています です。
コードは私にとって十分に明確に見えます。ネスト演算子と三項演算子を使用して短くすることができます。
if(one==null) {
return two==null ? 1 : 2;
}
if(two==null) {
return 3;
}
return isMatch(one,two) ? 4 : 5;
Java条件演算子を使用して1行で実行できます。
return (one==null?(two==null?1:2):(two==null?3:(isMatch(one,two)?4:5)));
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;
}
表現が好きです。
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);
どちらも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;
}
笑...プログラミングは美人コンテストではありません。あなたのコード
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;
すごいですね。まあ、素人にとっては「ブードゥー教」、「専門家」にとっては...「味」、「政治」、「宗教」について議論すべきではありません。しかし、パフォーマンスの観点からはそうです:
なぜ? 「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バイトを処理する必要があり、時間がかかることは明らかです...アプリが持つ「過剰な」コードほど、パフォーマンスが低下します。
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));
}
}