Краткая форма для Java Если инструкция Else
У меня есть метод, который проверяет наличие нулей. Есть ли способ уменьшить количество строк в методе? В настоящее время код выглядит "грязным":
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;
}
}
Ответы
Ответ 1
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;
}
Ответ 2
Я предпочитаю вложенные условия в таких случаях:
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);
}
Ответ 3
Поскольку фактическая цель функции состоит в том, чтобы обрабатывать объекты null
, сопоставляя их, Id обрабатывает все теги 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;
}
Это более краткий и читаемый, чем другие.
Тем не менее, реальные функции обычно не возвращают такие числовые коды. Если ваш метод не был упрощен, чтобы продемонстрировать проблему, Id настоятельно призывает вас пересмотреть логику и вместо этого написать что-то похожее на следующее:
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
, но опции на самом деле намного превосходят.
Ответ 4
Код выглядит достаточно ясным для меня. Вы можете сократить его с помощью вложенных и тройных операторов:
if(one==null) {
return two==null ? 1 : 2;
}
if(two==null) {
return 3;
}
return isMatch(one,two) ? 4 : 5;
Ответ 5
Это можно сделать в одной строке с использованием условного оператора Java:
return (one==null?(two==null?1:2):(two==null?3:(isMatch(one,two)?4:5)));
Ответ 6
Вы можете создать псевдо-поисковую таблицу. Некоторые люди нахмурились на вложенных тернарных операторах и сильно зависят от пробелов для удобочитаемости, но это может быть очень читаемый подход к условному возврату:
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;
}
Ответ 7
Мне нравятся выражения.
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);
Ответ 8
Избавление от операторов IF - хорошая забава. Использование карты - один из способов сделать это. Он не подходит для этого случая именно из-за вызова isMatch, но я предлагаю его в качестве альтернативы, который обрезает тело метода подобияCount на одну строку с одним IF
Следующий код имеет два IF. Если GetOrDefault не оценил второй аргумент, его можно было бы свести к единице. К сожалению, это делает так, что нулевая проверка внутри 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));
}
}
Ответ 9
Это должно быть немного быстрее, если ни один из них не равен 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;
}
Ответ 10
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-я версия быстрее
- вторая версия неуклюже (или медленнее)
WHY`?
Просто скомпилируйте его "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 байтов, и это требует времени... чем больше "лишних" кодов имеет приложение, тем хуже производительность.