【问题标题】:Compressing Similar if Statements (Java)压缩类似的 if 语句 (Java)
【发布时间】:2018-12-30 12:50:55
【问题描述】:

我试图根据传递给类的构造函数的值从 16 个数组中选择一个。输入的值将用于一系列将选择数组的 if 语句。像这样的

    package Model;

    import javax.swing.*;
    public class Die extends JButton{
         String letters[] = new String[6];
         public Die(int number){
               Controller con = new Controller();
               if(number==1){
                    for(int i = 0; i<5; i++}{
                        letters[i] = con.die1[i];
                    }
               }
               if(number==2){
                    for(int i = 0; i<5; i++}{
                        letters[i] = con.die2[i];
                    }
               }
               if(number==3){
                    for(int i = 0; i<5; i++}{
                        letters[i] = con.die3[i];
                    }
               }
         }
    }

(请记住,我没有检查此代码,也没有创建所有 16 个 if 语句)。
基本上我想以某种方式压缩这些 if 语句。有什么想法吗?

【问题讨论】:

标签: java


【解决方案1】:

声明一个Map&lt;Integer, String[]&gt;,将数字与字符串关联到每个die 数组,这样您就没有任何条件语句。

Controller con = new Controller();
Map<Integer, String[]> map = new HashMap<>();   
map.put(1, con.die1);
map.put(2, con.die2);
map.put(3, con.die3);


if(number>=1 && number<=3){
    for(int i = 0; i<5; i++}{
        letters[i] = map.get(number)[i];
    }
}

根据 Lino 的建议,您甚至可以将此映射移动到 Controller 类中,这在责任方面更有意义:

private Map<Integer, String[]> map = new HashMap<>();
public Controller(){
  map.put(1, die1);
  map.put(2, die2);
  map.put(3, die3);
}
public String getLetter(int number, int index){
    map.get(number)[index];
}

Die 客户端现在可能是:

Controller con = new Controller();       
if(number>=1 && number<=3){
    for(int i = 0; i<5; i++}{
        letters[i] = con.getLetter(number, i);
    }
}

【讨论】:

  • 最好的可能是在Controller 中声明该映射,然后仅通过方法调用将其公开
  • @Lino 在设计方面的优秀建议。我更新了。
  • 会再给你一个赞成票,但我只能按一次该按钮;)
  • con.die[i] 是如何工作的?根据 OP,这些是不同的数组 con.die1con.die2con.die3。您是否假设 con.die 是一个二维数组?如果是这样,那你为什么需要for循环循环5次,不应该是letters = map.get(i);吗?
  • 实际上,@user7 一个 2D 数组将是一个非常好的主意,我现在就实现它 - 谢谢。
【解决方案2】:

最好在if 分支中只选择应该迭代的数组:

String[] array;

if(number == 1){
    array = con.die1;
} else if(number == 2){
    array = con.die2;
} else if(number == 3){
    array = con.die3;
} else {
    // throw error or select a default array
}

然后在ifs 之外迭代选定的数组:

for(int i = 0; i<5; i++}{
     letters[i] = array[i];
}

对于未来的情况,最好分析 if 语句中的代码。

  1. 什么地方都一样?
  2. 各地有何不同?

从这两点你会看到:

  1. 您总是在遍历一个数组。
  2. 数组只是每次都不一样。

所以很容易看出,只是从 if 语句中提取出迭代的逻辑。并且选择数组留在里面。

【讨论】:

    【解决方案3】:

    由于所有循环都是相同的,您可以将 if 语句移动到循环内。此外,您可以将 if 语句更改为 switch,或者(可能可读性较差但更短)嵌套的三元 if:

    带开关:

    Controller con = new Controller();
    for(int i=0; i<5; i++){
      switch(number){
        case 1:
          letters[i] = con.die1[i];
          break;
        case 2:
          letters[i] = con.die2[i];
          break;
        case 3:
          letters[i] = con.die3[i];
          break;
        ...
        default:
          // Do something if the number is unknown
          break;
      }
    }
    

    使用三元 if:

    Controller con = new Controller();
    for(int i=0; i<5; i++){
      letters[i] = number==1 ? con.die1[i]
                   : number==2 ? con.die2[i]
                   : number==3 ? con.die3[i]
                   : ...;
    }
    

    三元 if 基本上是 if-else 的较短变体(以 &lt;condition&gt; ? &lt;value_if_true&gt; : &lt;else_value&gt; 的形式。这里是一个三元 if 的示例,这可能更容易理解:

    int a=...;
    System.out.println(a<5 ? "Less than 5" : a<15 ? "Less than 15" : "Else (15 or larger)");
    

    这与以下基本相同:

    if(a<5){
      System.out.println("Less than 5");
    } else if(a<15){
      System.out.println("Less than 15");
    } else{
      System.out.println("Else (15 or larger)");
    }
    

    Try it online.

    正如您所看到的,它的可读性要差得多,因此在大多数情况下我宁愿使用更长的 if 语句,但是对于您的代码,我个人会使用三元 if 以使代码更紧凑而不会太复杂。

    【讨论】:

    • 旁注:使用三元 if 时,建议使用括号,因为它会变得非常不可读
    • @Lino 好点。通常我使用换行符和缩进,但括号确实是嵌套三元 if 的好方法。
    【解决方案4】:

    我推荐switch statement

    String[] array;
    
    switch (number) {
            case 1:  array = con.die1;
                     break;
            case 2:  array = con.die2;
                     break;
            [...]
            case 16: array = con.die16;
                     break;
            default: // throw error or select a default array
        }
    

    【讨论】:

      【解决方案5】:

      您可以使用Java API 中的Arrays.copyOf 方法。

                     if(number==1){
                          letters = Arrays.copyOf(con.die1, 5); 
                     }
                     if(number==2){
                          letters = Arrays.copyOf(con.die2, 5); 
                     }
                     if(number==3){
                          letters = Arrays.copyOf(con.die3, 5); 
                     }
      

      【讨论】:

      • 根据 OPs 代码,只有前 5 个元素被复制到 letters 数组中。
      猜你喜欢
      • 1970-01-01
      • 2016-04-26
      • 2019-05-06
      • 1970-01-01
      • 1970-01-01
      • 2017-08-01
      • 2022-01-28
      • 1970-01-01
      • 2021-06-14
      相关资源
      最近更新 更多