【问题标题】:Reduce the number of variables used in my if-else statements减少 if-else 语句中使用的变量数量
【发布时间】:2011-11-21 07:37:32
【问题描述】:

我知道这听起来很糟糕,但在我的 java 程序中,我有大约 100 个 if-else 语句,所有这些语句都包含 3 个变量,这些变量必须对那些 if-else 块保持唯一,1 是一个标志,用于知道第一次是什么时候曾经碰到过那个 if-else 块,另外两个都是字符串,并且是临时变量,保存上次通过 if-else 块时使用的数据,因此可以将它与这次运行的数据进行比较,抱歉,如果这听起来很草率,我讨厌有这么多 if-else 块的想法,但现在我更关心变量,因为如果我为每个块创建 3 个变量,那就是额外的 300 个变量。关于我可以实施以减少变量数量的任何建议,我的一个想法是为所有标志使用 1 个数组,然后为每个 if-else 块保存 2 个字符串的 2d 数组。谢谢牛肉。

已编辑: 显示前 2 个 if-else 块的示例,所有其他块在内部都有相同的代码,只是标志和临时变量 ex 的名称不同。 ac101Flag, tempAC101Start, tempAC101End

                // AC 101
                if (room.equals("FEB 2009") || room.equals("FEB 2011") ||room.equals("FEB 2013") || room.equals("FEB 2015") || room.equals("FEB 2017") ||
                        room.equals("FEB 2021") || room.equals("FEB 2023") || room.equals("FEB 2025") || room.equals("FEB 2027") || room.equals("FEB 2029")) {
                    instanceNum = 4;
                    devID = 130200;
                    if (ac101Flag == false) {
                        Delete();
                        Insert();
                        ac101Flag = true;
                        tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
                        tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
                    }
                    //Insert();
                    else if (tempAC101Start <= (Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'))) && tempAC101End >= Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'))) {

                    }
                    else
                    {
                        Insert();
                        tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
                        tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
                    }   
                }
                // AC 102
                else if(room.equals("FEB 1130")) {
                    instanceNum = 4;
                    devID = 130400;
                    if (ac102Flag == false) {
                        Delete();
                        Insert();
                        ac102Flag = true;
                        tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
                        tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
                    }
                    //Insert();
                    else if (tempAC101Start <= (Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'))) && tempAC101End >= Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'))) {

                    }
                    else
                    {
                        Insert();
                        tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
                        tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
                    }   
                }

【问题讨论】:

  • 显示该代码的前几个 if/else 块。
  • @nos 参考编辑示例代码

标签: java arrays optimization variables reduce


【解决方案1】:

声明一个包含三个字段的类。为您需要维护的实例数创建此类的数组。

private class Vars{
   int val1;
   String val2, val3;
}

private Vars[] allVars = new Vars[300];

void myMethod(){
   if (condition1){
       allVals[0].val1 = ...;
   }
}

【讨论】:

    【解决方案2】:

    编辑:只是为了更具体地演示答案,我认为你想要这样的东西:

    class Foo // Rename this!
    {
        private double start;
        private double end;
        private boolean flag;
    
        public void handleValue(double newStart, double newEnd)
        {
            // Insert code here
        }
    }
    
    private static void insertFoo(Map<String, Foo> map, String... rooms)
    {
        Foo foo = new Foo();
        for (String room : rooms)
        {
            map.put(room, foo);
        }
    }
    
    ...
    HashMap<String, Foo> map = new HashMap<String, Foo>();
    insertFoo(map, "FEB 2009", "FEB 2011", ...);
    insertFoo(map, "FEB 1130");
    

    然后在你的循环中,只需使用:

    Foo foo = map.get(room);
    foo.update(start, end); // Parsed from the current finalStart/finalEnd
    

    如果没有看到您的代码,很难确定,但听起来您应该将所有这些都封装在一个数据结构中:

    • 三个变量(state 和 falg)
    • “某事”表示if 部分的条件。其确切性质将取决于您拥有什么

    然后,您可以遍历这些 ConditionBlock 对象(或您选择的任何名称)的列表,并检查该块是否在当前上下文中“匹配”,并在适当的地方进行更新。

    如果你能给我们一个原始代码的小例子,我们可以很容易地为你重构它。

    编辑:由于我显然还不清楚为了在 one 位置进行解析而引入局部变量,所以我会做这样的事情(作为 one 第一步):

    // TODO: Don't use double here - it's completely inappropriate. Use
    // BigDecimal if you absolutely must, but preferrably use a time-related
    // type, e.g. something from Joda Time (http://joda-time.sf.net)
    double parsedStart = Double.parseDouble(finalStart.substring(0, 5)
                                                      .replace(':', '.'));
    
    // TODO: Put all of these constants in a HashSet<String> and use contains
    if (room.equals("FEB 2009") || 
        room.equals("FEB 2011") ||
        room.equals("FEB 2013") || 
        room.equals("FEB 2015") || 
        room.equals("FEB 2017") ||
        room.equals("FEB 2021") || 
        room.equals("FEB 2023") || 
        room.equals("FEB 2025") || 
        room.equals("FEB 2027") || 
        room.equals("FEB 2029")) {
    
        instanceNum = 4;
        devID = 130200;
        // TODO: Change to if (!ac101Flag)
        if (ac101Flag == false) {
            // TODO: Rename these methods to follow Java naming conventions
            Delete();
            Insert();
            ac101Flag = true;
            tempAC101Start = parsedStart;
            tempAC101End = parsedEnd;
        }
        //Insert();
        else if (tempAC101Start <= parsedStart && tempAC101End >= parsedEnd) {
    
        }
        else
        {
            Insert();
            tempAC101Start = parsedStart;
            tempAC101End = parsedEnd;
        }   
    }
    

    【讨论】:

    • @Beef:if/else 块的逻辑有什么模式吗?你有什么理由打电话给parseDouble无处不在,而不是只在一个地方?
    • 我到处使用parseDouble的原因是每次它进入一个if-else块时finalStartfinalEnd的值会不同,它可以回到块,因此,如果它进入 AC101,它会保存这些温度,它可以在返回 AC101 之前跳转到 50 个其他块,但我仍然需要 AC101 数据,以便它何时返回,如果这有意义的话
    • @Beef:你在每一种情况中都调用Double.parseDouble(finalStart.substring(0, 5).replace(':', '.')——所以你可以在if块开始之前的一个地方这样做。您可以在每种情况下以不同的方式使用这些值,但它至少会消除那一点重复。
    • 我在Insert()方法中使用了finalStart的原始字符串,所以直到调用Insert()之后才能调用解析
    • @Beef:哦,你的意思是Insert 方法(对于Java 约定,应该命名为insert,顺便说一句)改变了finalStart 的值?哎呀。老实说,我不确定从你必须进行的重构是否是清理代码的最佳方式......我怀疑我会从头开始分析更大的问题。
    【解决方案3】:

    考虑使用多态性。

    每个块都有行为和数据。因此,让每个块成为实现接口的对象。

    每个块对象都可以像@Jon Skeet 建议的那样持有一个状态对象。

    首先,选择一个对象。这可能与您现有的 if 语句有关,或者如果可能,通过一些更简单的映射。

    然后,只需在您选择的对象上调用该方法即可。

    class BlockState {
      boolean hasBeenCalled = false;
      String last1;
      String last2;
    }
    
    class Block1 implements Runnable {
       BlockState m_blockState = new BlockState();
       public void run() { ... }
    }
    
    ... 
    class BlockN implements Runnable {
       BlockState m_blockState = new BlockState();
       public void run() { ... }
    }
    
    ...
    
    class LongChainOfIfs
      void foo() {
         Runnable runnable = null;
         if ( ... ) runnable = ...
         else if ( ... ) runnable = ...
         ...
         else runnable = ...
    
         runnable.run();
       }
     }
    

    【讨论】:

      【解决方案4】:

      您的问题中不清楚的一个问题是 if 块有多相似,无论如何,您可能有一个具有通用接口并采用上述想法的 if 块祖先类,为每个 if 块创建一个实例,将状态变量作为对象的一部分,然后创建这些对象的集合,然后循环遍历 if 块的集合,依次调用每个对象。每个 if 块实例都将继承公共变量并且对对象是唯一的(封装),并且每个块都可以为每个 if 块的每个特殊情况定制代码。

      定义每个实例的代码开销会更大,执行时间会更长,但您不必创建单独的变量,如果您愿意,您可以动态混合、匹配和更改 if 块的顺序。

      【讨论】:

        猜你喜欢
        • 2010-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-11
        • 1970-01-01
        • 2018-01-09
        • 2016-09-09
        相关资源
        最近更新 更多