【问题标题】:Use string in switch case in java在java中的switch case中使用字符串
【发布时间】:2012-05-01 16:52:32
【问题描述】:

在检查String 时,我需要将以下if 更改为switch-case,以提高圈复杂度。

String value = some methodx;
if ("apple".equals(value)) {
    method1;
}

if ("carrot".equals(value)) {
    method2;
}

if ("mango".equals(value)) {
    method3;
}

if ("orange".equals(value)) {
    method4;
}

但我不确定我会得到什么价值。

【问题讨论】:

  • 'if' 不是循环,它是一个测试某些条件的语句
  • 如果循环?真的吗?为了使用 switch 语句,你必须安装 jdk7。 stackoverflow.com/questions/338206/…
  • PS.. 更改为 switch 语句对您的复杂性无济于事.. 它仍然是相同数量的路径。只是实现方式不同。
  • 由于效率受到质疑,从第二个“if”开始,afk else if 会更好
  • 最好使用 else if ladder 而不是多个 if....

标签: java string switch-statement


【解决方案1】:

Java(版本 7 之前)不支持 switch/case 中的字符串。但是您可以通过使用枚举来实现所需的结果。

private enum Fruit {
    apple, carrot, mango, orange;
}

String value; // assume input
Fruit fruit = Fruit.valueOf(value); // surround with try/catch

switch(fruit) {
    case apple:
        method1;
        break;
    case carrot:
        method2;
        break;
    // etc...
}

【讨论】:

  • 我投了赞成票,但是.. 它会比你的 if "loop" 慢.. 这是 AFK 最好的方法。
  • 我有一个问题,我的“价值”不是一个常数,这个解决方案给我带来了问题。有什么解决办法???
  • "value" 在此示例中不是一个常数 - 它取决于用户输入。它应该对应于可能值的已知列表(由枚举定义),但不是必须的,因为任何“未知”值都可以被 try/catch 语句捕获并在那里处理。
  • 开关不会降低圈复杂度(至少在 PMD 计算时)。您必须使用枚举并将“命令”样式类引用放在地图中或枚举本身中的方法中。我昨天刚处理了一个类似的案例。
【解决方案2】:

学习使用else

由于value 永远不会同时等于两个不相等的字符串,因此只有 5 种可能的结果 - 一种代表您关心的每个值,另一种代表“以上都不是”。但是因为你的代码没有消除不能通过的测试,所以它有 16 个“可能”的路径(2 ^ 测试的数量),其中大多数永远不会被遵循。

对于else,唯一存在的路径是实际可能发生的 5 条路径。

String value = some methodx;
if ("apple".equals(value )) {
    method1;
}
else if ("carrot".equals(value )) {
    method2;
}
else if ("mango".equals(value )) {
    method3;
}
else if ("orance".equals(value )) {
    method4;
}

或者开始使用 JDK 7,它包括在 switch 语句中使用字符串的能力。当然,Java 只会将 switch 编译成 if/else 这样的构造...

【讨论】:

  • 它实际上是在hashcode上执行一个switch,然后执行if/else来解决hashcode冲突。
  • if else 很慢 :(
  • @Mann: if without else 平均来说更慢。 (它每次都会尝试每次比较。else 可以让你在找到匹配项后尽早完成。)最干净的方法确实是使用switch,它允许像这样的优化在你之前的评论中提到。但在 1.7 之前的 Java 版本中,这不是一个选项。
【解决方案3】:

现在每个人都至少在使用Java 7,对吧?这是原始问题的答案:

String myString = getFruitString();

switch (myString) {

    case "apple":
        method1();
        break;

    case "carrot":
        method2();
        break;

    case "mango":
        method3();
        break;

    case "orange":
        method4();
        break;
}

备注

  • case 语句等效于使用String.equals
  • 与往常一样,字符串匹配区分大小写。
  • 根据docs,这通常比使用链式if-else 语句(如cHao's answer)更快。

【讨论】:

    【解决方案4】:

    要降低圈复杂度,请使用地图:

    Map<String,Callable<Object>> map = new HashMap < > ( ) ;
    map . put ( "apple" , new Callable<Object> () { public Object call ( method1 ( ) ; return null ; } ) ;
    ...
    map . get ( x ) . call ( ) ;
    

    或多态性

    【讨论】:

      【解决方案5】:

      只是为了具体emory的答案,可执行代码如下:

        Map<String,Callable<USer>> map = new HashMap<String,Callable<User>>();
        map.put( "test" , new Callable<User> () { public User call (){ return fillUser("test" ); }} ) ;
        map.put( "admin" , new Callable<Utente> () { public Utente call (){  return fillUser("admin" ); }} ) ;
      

      其中用户是 POJO,然后

        User user = map.get(USERNAME).call();
      

      终于调用方法在某处:

       private User fillUser(String x){        
              User user = new User();
              // set something in User
              return user;
      }
      

      【讨论】:

        【解决方案6】:

        Java 不支持带字符串的 Switch-case。我想this 链接可以帮助你。 :)

        【讨论】:

          【解决方案7】:

          这是一种可能的 pre-1.7 方式,我不推荐:

          public class PoorSwitch
          {
              final static public int poorHash (String s) {
                  long l = 0L;
                  for (char c: s.toCharArray ()) {
                      l = 97*l + c;
                  }
                  return (int) l;
              }
          
              public static void main (String args[])
              {
                  String param = "foo";
                  if (args.length == 1)
                  {
                      param = args[0];
                  }
                  // uncomment these lines, to evaluate your hash
                  // test ("foo");
                  // test ("bar");
                  switch (poorHash (param)) {
                      // this doesn't work, since you need a literal constant
                      // so we have to evaluate our hash beforehand:
                      // case poorHash ("foo"): {
                      case 970596: {
                          System.out.println ("Foo!");
                          break;
                      }
                      // case poorHash ("bar"): {
                      case 931605: {
                          System.out.println ("Bar!");
                          break;
                      }
                      default: {
                          System.out.println ("unknown\t" + param);
                          break;
                      }
                  }
              }
          
              public static void test (String s)
              {
                  System.out.println ("Hash:\t " + s + " =\t" + poorHash (s));
              }
          }
          

          也许您可以在生成的代码中使用这样的技巧。否则我不能推荐它。与其说是哈希冲突的可能性让我担心,但如果有些东西混在一起(剪切和粘贴),就很难找到错误。 931605 不是一个好的文档。

          将其视为概念证明和好奇心。

          【讨论】:

          • 这类似于 HashMap 在内部所做的。但是 HashMap 具有处理(远程)冲突可能性的代码。 HashMap 隐藏了复杂度,降低了圈复杂度。
          • HashMap 有,但 hashcode 没有。如果建议使用完善的、经过测试的 Java "foo".hashCode(),你可能是对的,但有没有保证它永远不会改变?是否像公共 API 一样保证价值/算法?如果您提供自己的 hashCode,您至少可以控制它。
          • 保证"foo".hashCode() 将始终返回相同的值。仅仅是因为在字符串上使用switch 的Java7+ 代码编译为完全假设该不变属性的代码。所以它不能在未来的版本中改变,而且更简单地看到算法从 Java 1.0 到 Java 7 也没有改变。但是你的代码应该在case 语句中使用equals 来防止哈希冲突。
          【解决方案8】:

          我们可以在数据类型兼容的 int :short,Shor,byte,Byte,int,Integer,char,Character 或 enum 类型上应用 Switch。

          【讨论】:

            【解决方案9】:

            使用 switch 语句评估 String 变量已在 Java SE 7 中实现,因此它仅适用于 java 7。您还可以查看这个新的 feature 在 JDK 7 中是如何实现的。

            【讨论】:

              【解决方案10】:

              Java 8 支持字符串 switchcase。

              String type = "apple";
              
              switch(type){
                  case "apple":
                     //statements
                  break;
                  default:
                     //statements
                  break; }
              

              【讨论】:

              • 还有 Java 7,正如多次提到的那样。
              【解决方案11】:
                  String name,lname;
               name= JOptionPane.showInputDialog(null,"Enter your name");
                 lname= JOptionPane.showInputDialog(null,"Enter your father name");
                  if(name.equals("Ahmad")){
                     JOptionPane.showMessageDialog(null,"welcome "+name);
                  }
                  if(lname.equals("Khan"))
                 JOptionPane.showMessageDialog(null,"Name : "+name +"\nLast name :"+lname ); 
              
                  else {
                     JOptionPane.showMessageDialog(null,"try again " );
                  } 
                }}
              

              【讨论】:

                【解决方案12】:

                不是很漂亮,但这是另一种方式:

                String runFct = 
                        queryType.equals("eq") ? "method1":
                        queryType.equals("L_L")? "method2":
                        queryType.equals("L_R")? "method3":
                        queryType.equals("L_LR")? "method4":
                            "method5";
                Method m = this.getClass().getMethod(runFct);
                m.invoke(this);
                

                【讨论】:

                  【解决方案13】:
                  String value = someMethod();
                  switch(0) {
                  default:
                      if ("apple".equals(value)) {
                          method1();
                          break;
                      }
                      if ("carrot".equals(value)) {
                          method2();
                          break;
                      }
                      if ("mango".equals(value)) {
                          method3();
                          break;
                      }
                      if ("orance".equals(value)) {
                          method4();
                          break;
                      }
                  }
                  

                  【讨论】:

                  • 奥奇。一个不必要的switch 声明只是为了拥有它。
                  • 请删除你的答案。
                  猜你喜欢
                  • 1970-01-01
                  • 2020-12-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多