【问题标题】:Short form for Java If Else statementJava If Else 语句的简写形式
【发布时间】:2017-06-19 09:08:16
【问题描述】:

我有一个检查空值的方法。有没有办法减少方法中的行数?目前,代码看起来很“脏”:

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;
    }

}

【问题讨论】:

  • 首先,如果return 值在if 块内,则不需要使用else
  • 你可以使用三元条件。
  • 使用简写或if-else没有性能差异,最好写可读的代码让ppl理解你的代码,上面这段代码已经很清楚了。
  • 你说你想减少代码行数。原因是您的示例的代码气味。更少的行不会解决这个问题。复杂性会降低。
  • 你能重构 isMatch 以返回 4 或 5 而不是布尔值吗?这将允许您简化最后一个 else

标签: java if-statement ternary-operator short


【解决方案1】:

代码对我来说已经足够清晰了。您可以使用嵌套和三元运算符使其更短:

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

【讨论】:

  • 我不确定更短的代码是否比更易读的代码更好。如果没有 if 已满,我会在块的末尾留下四个 if 而没有 elsereturn 5;
  • @RadekJ 我同意可读性更高的版本更可取。不过,在线上的一个三元运算符并没有真正降低可读性。在我看来,守卫声明更容易阅读。不过,发布您的版本,我会赞成 :)
  • @RadekJ 实际上,Manh Le 的回答与您的描述非常接近。
  • 是的,我同意,我会写像 Manh Le 这样的东西,但你的代码是很好的妥协 :)
【解决方案2】:
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;
}

【讨论】:

  • 您甚至可以从第二个if 中删除&& two!=null,因为当这部分代码执行时,它总是不是null。您还可以使用assert 来断言某些执行路径上变量的非空性(无论如何,当-ea 时,这应该是默认值)。
  • 这是更易读的选择。唯一让我内心的完美主义者对此解​​决方案感到困惑的是,您必须对案例 2 和案例 3 多次执行相同的 null 检查。再说一次,如果结果是一个问题,您可以随时解决它。跨度>
  • 为什么isMatch(one, two) 是三元组?为什么不只是另一个 if 语句?这将更适合现有流程,并且阅读更流畅。
  • @CAD97 我实际上喜欢将assert 用于100% 始终正确的代码即使-ea 未启用,因为它有点像更多在这一点上的信息性评论。我只将它用于只能是真实的事情,因为你不能依赖-ea 的存在。
  • 我不明白最后一个换行格式背后的逻辑。最后一行似乎应该是两行:`if(isMatch(one,two) { return 4; } return 5;
【解决方案3】:

在这种情况下我更喜欢嵌套条件:

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);
}

【讨论】:

  • 努力值得点赞
  • 我更喜欢第二个。嵌套的 if-else 使第一个很难一目了然,imo。这可能是因为最后一次返回与那里的条件之间的距离。
  • 我不得不说我发现这种陈述逻辑的方式非常复杂。它将null 检查分为两个一般情况one == nullone != null,实际上,我们真的onetwo 是否是null 感兴趣,或者两者都不。因此,我建议不要使用此处提供的所有选项。
  • @KonradRudolph 对于这 4 种情况,我们有不同的返回值,都是 null,都不是 null,只有一个是 null,只有两个是 null,所以我不确定你为什么说我们是 @ 987654330@.
  • 您可以在前两个示例中去掉elseif (one==null) { return foo; } return bar;
【解决方案4】:

使用Java条件运算符可以在一行中完成:

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

【讨论】:

  • 一件事情可以做,并不意味着它应该做:)
  • 我以为用户问的是更短的方式。 :) 所以不知道为什么要投反对票。
  • @SachinSarawgi 我为你投票,因为无论如何都没有理由拒绝投票
  • 感谢@PSo 理解答案。
  • 你的回答确实不正确,但这个想法确实退出了,不错的一个
【解决方案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而是optionals are in fact far superior好。

【讨论】:

  • 很好的答案,在改进代码之前先看看解决方案总是好的。
【解决方案6】:

摆脱 IF 语句很有趣。使用地图是执行此操作的一种方法。由于调用了 isMatch,它并不完全适合这种情况,但我提供了它作为替代方案,它将similarityCount 方法主体切割成带有一个 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));
    }

}

【讨论】:

  • 编写的每一行代码都是一种责任。 wiki.c2.com/?SoftwareAsLiability 。此外,KISS 和 YAGNI 原则也适用。
  • 这个解决方案的圈复杂度要低得多——根据 isMatch 的实现方式,2 个 ifs 与(至少)5 个。我同意对于这种情况,这不是一个简洁的解决方案,但对于许多 if/switch 语句,这种方法可以显着降低复杂性。
  • 我看不出 YAGNI 是如何应用的。据我所知,所有代码都在使用中
  • 如果我正确阅读了您的论点,您选择了一张地图以实现未来的可扩展性。与之相反的论点是 YAGNI。
【解决方案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 进行了可读性较低的检查,您的方法的用户需要了解整数值中隐含的约定。

此外,当您需要检查字符串可能为空时是否相等时,这里有一个简单的解决方案:

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

【讨论】:

    【解决方案8】:

    可以创建一个伪查找表。有些人不喜欢嵌套的三元运算符,它高度依赖空格来提高可读性,但它可以是一种非常易读的条件返回方法:

    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;
    }
    

    【讨论】:

      【解决方案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;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-02-12
        • 1970-01-01
        • 2013-08-18
        • 2012-04-09
        • 2014-11-04
        • 2015-03-22
        • 1970-01-01
        • 2011-05-26
        • 1970-01-01
        相关资源
        最近更新 更多