Краткая форма для оператора 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 байт должны быть обработаны, и это занимает время...чем больше "чрезмерных" кодов у приложения, тем хуже производительность станет.