简体   繁体   中英

A large switch statement or several small switch statements?

I am wondering if there any performance different between a large switch statement and several small switch statements.

Large switch statement with hundreds of cases.

switch(quest){
            case 1: quest1(); break;
            case 2: quest2(); break;
            .
            .
            .
            case 196: quest196(); break;
            case 197: quest197(); break;
            .
            .
            .
        }

or several smaller switch statement with 30 cases each.

if (quest <= 30) {
        switch (quest) {
            case 1: quest1(); break;    
            case 2: quest2(); break;    
            case 3: quest3(); break;
            .
            .
            case 30: quest30(); break;
            default: 
                return;
        }
    } else if (quest <= 60) {
        switch (quest) {
            case 31: quest31(); break;  
            case 32: quest32(); break;  
            case 33: quest33(); break;
            .
            . 
            .
            case 60: quest60(); break;
            default:
                return;
        }
    } 
  .
  .
  .

Also, I know reflection will be a lot easier to code, but will that cause a large overhead?

something like this.

try {
            Method method =Logic.class.getMethod("quest"+quest);
            method.invoke(this);
        } catch (NoSuchMethodException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Thanks in advance.

The difference between a large switch and a chain of if / then / else statements that include smaller switch is that a single switch will find the code to execute in a single lookup, while a chain of conditionals may need several individual checks before arriving at the switch statement of interest. Once the switch statement is found, it takes roughly the same time to do a dispatch, almost no matter how many case labels there are. A single switch statement is also more readable, so I would prefer it to a chain of conditionals.

Although reflection does have an overhead, it is not terrible, so if your questNNN methods are not extremely fast, the overhead of reflection is not going to matter much. You could even speed it up by preparing an array of Method objects, and populate it upfront to avoid the Logic.class.getMethod("quest"+quest) calls at the time when you dispatch the call.

Finally, you could create an array of Runnable objects, and encapsulate calls of questNNN inside them:

Runnable[] dispatch = new Runnable[] {
    new Runnable() { public void run() { quest0(); } }
,   new Runnable() { public void run() { quest1(); } }
,   new Runnable() { public void run() { quest2(); } }
,   new Runnable() { public void run() { quest3(); } }
,   new Runnable() { public void run() { quest4(); } }
...
,   new Runnable() { public void run() { quest59(); } }
,   new Runnable() { public void run() { quest60(); } }
};

Now you can call dispatch[NNN].run() to call your questNNN method.

If you really want to optimize do it for the programmers that will come after you. Use a proper structure that will make it obviously optimal for speed while patently clear and simple.

interface Quest {

    void quest();
}
static Set<Quest> allQuests = new HashSet<>();

enum MontyPythonQuests implements Quest {

    MakeMeAShrubbery {
                @Override
                public void quest() {
                    System.out.println("Build me a SHRUBBERY!!!!!");
                }
            },
    SeekTheHolyGrail {
                @Override
                public void quest() {
                    System.out.println("Brave Sir Basil ran away!");
                }
            };

    @Override
    public void quest() {
        // Simplistic default implementation just prints the name of the enum.
        System.out.println(this.name());
    }

    MontyPythonQuests() {
        // All quests are added to the list.
        allQuests.add(this);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM