二维开关语句的可读替代方案?

时间:2013-10-12 00:27:19

标签: java arrays switch-statement readability

我需要触发不同的方法,具体取决于parentchild的值,它们是同一枚举类型的不同值。目前我这样做:

switch (parent)
{
  case DEPARTMENT:
  {
    switch (child)
    {
      case TERMINAL:
      {
        event1();
        break;
      }
      case OPERATOR:
      {
        event2();
        break;
      }
    }
    break;
  }
  case OPERATOR:
  {
    switch (child)
    {
      case TERMINAL:
      {
        event3();
        break;
      }
    }
    break;
  }
}

实际代码包含5-10个案例,每个案例执行一行或多行代码(带有多个参数的方法)。

我尝试使用Runnable填充二维数组,但执行速度慢了2倍。

是否有另一种写作方式,这种方式更具可读性,但几乎同样快?

5 个答案:

答案 0 :(得分:1)

class SwitchTable {
    private static class EventKey {
        private EnumType parent;
        private EnumType child;
        public EventKey (EnumType p, EnumType c) { parent=p; child=c; }
        public int HashCode () { ...something... }
    } 
    private HashMap<EventKey, Integer> events;
    public void setEvent (EnumType parent, EnumType child, int eventNumber) {
         ... add a map entry to events that maps new EventKey(parent,child) 
         ... to eventNumber
    }
    public int whichEvent (EnumType parent, EnumType child) {
         ... return the map entry for new EventKey(parent,child) or 0 if not found
    }
}

// do this once to set up
SwitchTable switches = new SwitchTable();
switches.setEvent (EnumType.DEPARTMENT, EnumType.TERMINAL, 1);
switches.setEvent (EnumType.DEPARTMENT, EnumType.OPERATOR, 2);
switches.setEvent (EnumType.OPERATOR, EnumType.TERMINAL, 3);

// then
switch (switches.whichEvent(parent, child)) {
    case 1:  event1();  break;
    case 2:  event2();  break;
    case 3:  event3();  break;
}

我懒得填写所有细节,但你明白了。即使父和子的枚举类型不同,这也应该有效。您可以为SwitchTable使用不同的实现(例如,设置1维或2维数组来保存事件值而不是HashMap)。我没有对此进行过测试,也不知道它是如何比较速度的。我希望我没有做出任何愚蠢的语法错误。

编辑:whichEvent不必返回整数。您可以将其设置为新的enum类型,其名称反映了您可能要采取的操作类型。这应该会提高可读性。

答案 1 :(得分:1)

根据parentchild的组合值计算的整数选择器会更快:

public enum Stuff { DEPARTMENT, OPERATOR, TERMINAL };
Stuff parent = ...;
Stuff child  = ...;

int selector = parent.ordinal() * Stuff.values().length + child.ordinal();
switch(selector)
{
    case 0 : // parent=DEPARTMENT child=DEPARTMENT
        ...
    case 1 : // parent=DEPARTMENT child=OPERATOR
        ...
        ...
    case 3 : // parent=OPERATOR child=DEPARTMENT
        ...
    case 8:  // parent=TERMINAL child=TERMINAL
        ...
}

某些组合可能没有意义,只是省略它们并提供default,其中没有任何内容。您还可以在枚举中定义常量:

private static final int n = values().length; // for brevity
public static final int DEPARTMENT_DEPARTMENT = DEPARTMENT.ordinal() * n + DEPARTMENT.ordinal()
        ...

并在案例陈述中使用它们。

答案 2 :(得分:1)

大多数情况下,存档可读性会影响性能。这是一个使用java7 ONLY 的解决方案。

public class SwitchArray {

    public enum Stuff {
        DEPARTMENT, OPERATOR, TERMINAL
    };

    static Stuff parent = Stuff.DEPARTMENT;
    static Stuff child = Stuff.OPERATOR;

    /**
     * @param args
     */
    public static void main(String[] args) {
        switch (SwitchArray.parent.toString() + "_" + SwitchArray.child.toString()) {
        case "DEPARTMENT_OPERATOR":
            System.out.println("hey!");
            break;
        case "DEPARTMENT_TERMINAL":
            System.out.println("ha!");
            break;
        default:
            break;
        }
    }

}

答案 3 :(得分:0)

为你的枚举添加一个方法(我称之为MyEnum)

public void doFireEvent(MyEnum child){   //每个枚举都有一个开关 }

稍微清洁的IMO,至少它将所有代码移动到枚举类,所以你不会看到它。 : - )

(稍后补充)。这样做的一个缺点是你的MyEnum类必须知道/访问event1()等方法,这可能是不可能或不合适的。

答案 4 :(得分:0)

只需使用更好的缩进和格式化技术,并将所有这些脏逻辑封装在枚举本身中,您的代码就可以变得更具可读性。它 这真的是你的格式,而不是任何使它难以追踪的东西。

public enum MyEnum {

    OPERATOR, TERMINAL;

    public static void execute(MyEnum parent, MyEnum child) {
        switch(parent) {
            case OPERATOR:
                switch(child) {
                    case OPERATOR: event1(); break;
                    case TERMINAL: event2(); break;
                }
            break;
            case TERMINAL:
                switch(child) {
                    case TERMINAL: event3(); break;
                }
            break;
        }
    }

}