【问题标题】:Java compare values, best wayJava比较值,最好的方法
【发布时间】:2020-02-05 23:14:29
【问题描述】:

我有这样的方法

private boolean validGrade(final StringBuilder grade) {
   boolean isValid = false;
   String semester = "semester"; 

   if ((grade.toString().contains("2o") && grade.toString().contains(semester))
                    || (grade.toString().contains("4o") && grade.toString().contains(semester))
                    || (grade.toString().contains("6o") && grade.toString().contains(semester))
                    || (grade.toString().contains("8o") && grade.toString().contains(semester))) {
    isValid = true;
            }
    }

我想用这样的方式替换它:

private boolean doValidGradoAntComp(final StringBuilder grade) {
        boolean isValid = false;

        switch (grade.toString()) {
        case "2o semester":
            isValid = true;
            break;
        case "4o semester":
            isValid = true;
            break;
        case "6o semester":
            isValid = true;
            break;
        case "8o semester":
            isValid = true;
            break;
        default:
            break;
        }

        return isValid;
    }

我的疑问是: 哪一个更好? 两者的工作方式相同?

【问题讨论】:

  • 您认为这两种方法是否相同? contains 不同,switch case 不同
  • 我建议在条件之外设置值(在一些单独的布尔变量中。例如,Boolean bool = grade.toString().contains(semester);
  • 好吧,我想说第二个选项更具可读性,因此不太容易出错。此外,它不需要多次调用grade.toString()。但是,第一个变体允许比第二个变体更多的变体,即 "something semester whatever 2o" 将匹配 contains("2o") 和 contains("semester")。
  • 如果所有允许的变体都像上面的开关一样,您也可以在一行中完成:boolean isValid = grade.toString().matches("[2468]o semester");
  • 如何使用 static Set<String> sets,其中包含 ("2o", "4o", "8o"...)。然后使用sets.contains做判断​​过程。

标签: java performance methods switch-statement comparison


【解决方案1】:

为什么不重复这些可能性呢?

private boolean validGrade(final StringBuilder grade) {
    String gradeString = grade.toString();
    return List.of("2o", "4o", "6o", "8o")
        .stream()
        .map(x -> x + " semester")
        .collect(Collectors.toSet())
        .contains(gradeString);
}

或者,如果您不是在寻找精确匹配,请执行以下操作:

private boolean validGrade(final StringBuilder grade) {
    String gradeString = grade.toString();
    return gradeString.contains("semester") && List.of("2o", "4o", "6o", "8o")
        .stream()
        .anyMatch(gradeString::contains);
}

最后,如果你的匹配集不灵活(总是"2o", "4o", "6o", "8o"),那么你可以只使用正则表达式:

private boolean validGrade(final StringBuilder grade) {
    return grade.toString().matches("[2468]o semester"); //exact match
//  return grade.toString().matches("[2468]o.*semester|semester.*[2468]o"); //loose match
//  return grade.toString().matches(".*([2468]o.*semester|semester.*[2468]o).*"); //equivalent to contains
}

【讨论】:

  • 我会将正则表达式扩展到.*(the current regex).* 以实际提供松散匹配,因为String.matches() 仅在整个 字符串匹配时才返回true。这样,正则表达式将更紧密地匹配第一种方法的contains(...) 逻辑。 :)
  • @Thomas 事实上,我考虑过。不确定这么长时间后编辑答案是否值得,但这绝对是值得保留在 cmets 中的一个好点。无论如何,它现在就在那里。
【解决方案2】:

两种方法都不一样,在第一种方法中,您使用contains 检查grade 中存在的两个字符串(例如2o 和grade 中的semester)。但在第二个方法中,您正在检查 grade 是否等于 2o semester。我更喜欢收集所有这些来列出和使用anyMatch

List<String> list = List.of("2o","4o","6o","8o");

if(list.stream().anyMatch(val->grade.contains(val) && grade.contains(semester))) {

【讨论】:

    【解决方案3】:

    两者的目的相同,但各有不同、弱点和优势。

    如果/否则

    • 读写困难(代码很难写,因为你需要在一个语句中包含多值检查)

    • 您的选择是您的代码是否会被执行。

    • 与开关一样,如果其值不为真(否则),您可以创建default 语句。

    切换

    • 易于编写和阅读代码。

    • 您将始终输入 switch 块,如果没有与您输入的值匹配的大小写将默认。

    • 你只能使用char或intcase。

    • 你只有一种条件,不像 if / else 你可以有几种条件。

    结论:

    在性能问题上,切换通常更快,但差异很小。

    如果您要检查的情况很少,我会使用if/else,但在您的情况下,建议您使用switch case 来检查您仅在一个代码块中执行的检查次数。

    【讨论】:

      【解决方案4】:

      Regex 可能比 if-else 或 switch 慢。但在你的情况下,我会更加重视可读性并使用正则表达式。

      private boolean validGrade(final StringBuilder grade) {
          return grade.toString().matches("(2o|4o|6o|8o) semester");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-02
        • 2021-04-22
        • 1970-01-01
        • 2018-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多