Краткая форма для оператора 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;
}
}
10 ответов
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;
}
это и более сжатый и более читаемый, чем другие варианты.
что сказал:реальные функции обычно не возвращают такие числовые коды. Если ваш метод не был упрощен для иллюстрации проблемы, я настоятельно призываю вас пересмотреть логику и вместо этого написать что-то похожее на то, что следует:
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.util.Optional<Boolean>
в Java 8:
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:
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);
избавление от заявлений IF-это хорошее развлечение. Использование карты-один из способов сделать это. Он не подходит для этого случая именно из-за вызова isMatch, но я предлагаю его в качестве альтернативы, которая режет тело метода similarityCount на одну строку с одним IF
следующий код имеет два IFs. Если GetOrDefault не оценил второй аргумент, его можно свести к одному. К сожалению, это делает так, что проверка null внутри isMatch необходима.
вы могли бы пойти много продолжайте, если хотите. Например, 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));
}
}
Это должно быть немного быстрее, если ни один из них не равен null, так как в этом случае он выполняет только один оператор "if".
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;
}
LOL...Программирование - это не конкурс красоты. Коды
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;
здорово, не так ли ? Ну, для непрофессионалов это "вуду", для "экспертов"...не следует обсуждать "вкус", "политику"и " религию". Но с точки зрения производительности это так:
- 1-я версия быстрее!--12-->
- 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 байт
Второй Вариант:
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 байт должны быть обработаны, и это занимает время...чем больше "чрезмерных" кодов у приложения, тем хуже производительность станет.