代码之家  ›  专栏  ›  技术社区  ›  Ande Turner

Java:If与Switch

  •  17
  • Ande Turner  · 技术社区  · 17 年前

    if ( WORD[ INDEX ] == 'A' ) branch = BRANCH.A;
    /* B through to Y */
    if ( WORD[ INDEX ] == 'Z' ) branch = BRANCH.Z;
    

    b

    switch ( WORD[ INDEX ] ) {
        case 'A' : branch = BRANCH.A; break;
        /* B through to Y */
        case 'Z' : branch = BRANCH.Z; break;
    }
    




    编辑:

    以下一些答案涉及上述方法的替代方法。

    以下内容似乎证实了思维实验的失败。

    public class Dictionary {
        private static Dictionary ROOT;
        private boolean terminus;
        private Dictionary A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z;
        private static Dictionary instantiate( final Dictionary DICTIONARY ) {
            return ( DICTIONARY == null ) ? new Dictionary() : DICTIONARY;
        }
        private Dictionary() {
            this.terminus = false;
            this.A = this.B = this.C = this.D = this.E = this.F = this.G = this.H = this.I = this.J = this.K = this.L = this.M = this.N = this.O = this.P = this.Q = this.R = this.S = this.T = this.U = this.V = this.W = this.X = this.Y = this.Z = null;
        }
        public static void add( final String...STRINGS ) {
            Dictionary.ROOT = Dictionary.instantiate( Dictionary.ROOT );
            for ( final String STRING : STRINGS ) Dictionary.add( STRING.toUpperCase().toCharArray(), Dictionary.ROOT , 0, STRING.length() - 1 );
        }
        private static void add( final char[] WORD, final Dictionary BRANCH, final int INDEX, final int INDEX_LIMIT ) {
            Dictionary branch = null;
            switch ( WORD[ INDEX ] ) {
            case 'A' : branch = BRANCH.A = Dictionary.instantiate( BRANCH.A ); break;
            case 'B' : branch = BRANCH.B = Dictionary.instantiate( BRANCH.B ); break;
            case 'C' : branch = BRANCH.C = Dictionary.instantiate( BRANCH.C ); break;
            case 'D' : branch = BRANCH.D = Dictionary.instantiate( BRANCH.D ); break;
            case 'E' : branch = BRANCH.E = Dictionary.instantiate( BRANCH.E ); break;
            case 'F' : branch = BRANCH.F = Dictionary.instantiate( BRANCH.F ); break;
            case 'G' : branch = BRANCH.G = Dictionary.instantiate( BRANCH.G ); break;
            case 'H' : branch = BRANCH.H = Dictionary.instantiate( BRANCH.H ); break;
            case 'I' : branch = BRANCH.I = Dictionary.instantiate( BRANCH.I ); break;
            case 'J' : branch = BRANCH.J = Dictionary.instantiate( BRANCH.J ); break;
            case 'K' : branch = BRANCH.K = Dictionary.instantiate( BRANCH.K ); break;
            case 'L' : branch = BRANCH.L = Dictionary.instantiate( BRANCH.L ); break;
            case 'M' : branch = BRANCH.M = Dictionary.instantiate( BRANCH.M ); break;
            case 'N' : branch = BRANCH.N = Dictionary.instantiate( BRANCH.N ); break;
            case 'O' : branch = BRANCH.O = Dictionary.instantiate( BRANCH.O ); break;
            case 'P' : branch = BRANCH.P = Dictionary.instantiate( BRANCH.P ); break;
            case 'Q' : branch = BRANCH.Q = Dictionary.instantiate( BRANCH.Q ); break;
            case 'R' : branch = BRANCH.R = Dictionary.instantiate( BRANCH.R ); break;
            case 'S' : branch = BRANCH.S = Dictionary.instantiate( BRANCH.S ); break;
            case 'T' : branch = BRANCH.T = Dictionary.instantiate( BRANCH.T ); break;
            case 'U' : branch = BRANCH.U = Dictionary.instantiate( BRANCH.U ); break;
            case 'V' : branch = BRANCH.V = Dictionary.instantiate( BRANCH.V ); break;
            case 'W' : branch = BRANCH.W = Dictionary.instantiate( BRANCH.W ); break;
            case 'X' : branch = BRANCH.X = Dictionary.instantiate( BRANCH.X ); break;
            case 'Y' : branch = BRANCH.Y = Dictionary.instantiate( BRANCH.Y ); break;
            case 'Z' : branch = BRANCH.Z = Dictionary.instantiate( BRANCH.Z ); break;
            }   
            if ( INDEX == INDEX_LIMIT ) branch.terminus = true;
            else Dictionary.add( WORD, branch, INDEX + 1, INDEX_LIMIT );
        }
        public static boolean is( final String STRING ) {
            Dictionary.ROOT = Dictionary.instantiate( Dictionary.ROOT );
            return Dictionary.is( STRING.toUpperCase().toCharArray(), Dictionary.ROOT, 0, STRING.length() - 1 );
        }
        private static boolean is( final char[] WORD, final Dictionary BRANCH, final int INDEX, final int INDEX_LIMIT ) {
            Dictionary branch = null;
            switch ( WORD[ INDEX ] ) {
            case 'A' : branch = BRANCH.A; break;
            case 'B' : branch = BRANCH.B; break;
            case 'C' : branch = BRANCH.C; break;
            case 'D' : branch = BRANCH.D; break;
            case 'E' : branch = BRANCH.E; break;
            case 'F' : branch = BRANCH.F; break;
            case 'G' : branch = BRANCH.G; break;
            case 'H' : branch = BRANCH.H; break;
            case 'I' : branch = BRANCH.I; break;
            case 'J' : branch = BRANCH.J; break;
            case 'K' : branch = BRANCH.K; break;
            case 'L' : branch = BRANCH.L; break;
            case 'M' : branch = BRANCH.M; break;
            case 'N' : branch = BRANCH.N; break;
            case 'O' : branch = BRANCH.O; break;
            case 'P' : branch = BRANCH.P; break;
            case 'Q' : branch = BRANCH.Q; break;
            case 'R' : branch = BRANCH.R; break;
            case 'S' : branch = BRANCH.S; break;
            case 'T' : branch = BRANCH.T; break;
            case 'U' : branch = BRANCH.U; break;
            case 'V' : branch = BRANCH.V; break;
            case 'W' : branch = BRANCH.W; break;
            case 'X' : branch = BRANCH.X; break;
            case 'Y' : branch = BRANCH.Y; break;
            case 'Z' : branch = BRANCH.Z; break;
            }
            if ( branch == null ) return false;
            if ( INDEX == INDEX_LIMIT ) return branch.terminus;
            else return Dictionary.is( WORD, branch, INDEX + 1, INDEX_LIMIT );
        }
    }
    
    11 回复  |  直到 16 年前
        1
  •  24
  •   Carl Manaster    17 年前

    不要担心性能;使用最能表达你正在做什么的语法。只有在你(a)表现出绩效不足之后;以及(b)将其本地化到所讨论的例程中,只有这样你才应该担心性能。在我看来,这里的case语法更合适。

        2
  •  23
  •   Tom Hawtin - tackline    17 年前

    tableswitch lookupswitch 一个假设密钥集很密集,另一个假设是稀疏的。请参阅以下说明 compiling switch in the JVM spec 。对于枚举,找到序号,然后代码继续作为 int switch String

        3
  •  7
  •   Clint    17 年前

    看起来你已经枚举了这些值,所以也许枚举是正确的?

    enum BRANCH {
      A,B, ... Y,Z;
    }
    

    BRANCH branch = BRANCH.valueOf( WORD[ INDEX ] );
    

    此外,您的代码中可能存在一个错误 "A" == "A" 根据“A”的对象标识,可能为假。

        4
  •  4
  •   Jack Leow    17 年前

    switch ( WORD[ INDEX ] ) {
        case 'A' : branch = BRANCH.A; break;
        /* B through to Y */
        case 'Z' : branch = BRANCH.Z; break;
    }
    

    我认为这里的性能差异不会太大,但如果你真的关心性能,并且这段代码执行得非常频繁,那么还有另一个选择:

    // Warning, untested code.
    BRANCH[] branchLookUp = {BRANCH.A, BRANCH.B, ..., BRANCH.Z};
    
    branch = branchLookUp[WORD[INDEX] - 'A'];
    

    不过,一定要把它封装起来并很好地记录下来。

        5
  •  3
  •   Cambium    17 年前

    老实说,我认为在这种情况下,性能并不重要。这实际上取决于编译器及其优化。

        6
  •  3
  •   Nick Lewis    17 年前

    此外,对于像这样的案例,如果你的案例是互斥的,使用if/else-if会比if有所改进。在匹配A后再进行25次检查是没有意义的。

    但基本上,任何性能差异都可以忽略不计,您应该使用最正确的语法,在本例中是switch语句。不过,一定要用破口把箱子分开。

        7
  •  3
  •   Carl Manaster    17 年前

    import java.util.HashMap;
    
    public class Dictionary {
        private static Dictionary                       ROOT;
        private boolean                                 terminus;
        private final HashMap<Character, Dictionary>    dictionaries    = new HashMap<Character, Dictionary>();
    
        private void ensureBranch(char c) {
            if (getBranch(c) != null)
                return;
            dictionaries.put(c, new Dictionary());
        }
    
        private Dictionary getBranch(char c) {
            return dictionaries.get(c);
        }
    
        public static boolean is(final String string) {
            ensureRoot();
            return is(chars(string), ROOT, 0, string.length() - 1);
        }
    
        public static void add(final String... strings) {
            ensureRoot();
            for (final String string : strings)
                add(chars(string), ROOT, 0, string.length() - 1);
        }
    
        private static void ensureRoot() {
            if (ROOT == null)
                ROOT = new Dictionary();
        }
    
        private static char[] chars(final String string) {
            return string.toUpperCase().toCharArray();
        }
    
        private Dictionary() {
            this.terminus = false;
        }
    
        private static void add(final char[] word, final Dictionary dictionary, final int index, final int limit) {
            Dictionary branch = getBranch(word, dictionary, index);
            if (index == limit)
                branch.terminus = true;
            else
                add(word, branch, index + 1, limit);
        }
    
        private static Dictionary getBranch(final char[] word, final Dictionary dictionary, final int index) {
            final char c = word[index];
            dictionary.ensureBranch(c);
            return dictionary.getBranch(c);
        }
    
        private static boolean is(final char[] word, final Dictionary dictionary, final int index, final int limit) {
            Dictionary branch = dictionary.getBranch(word[index]);
            if (branch == null)
                return false;
            if (index == limit)
                return branch.terminus;
            return is(word, branch, index + 1, limit);
        }
    }
    
        8
  •  2
  •   Jack Leow    17 年前

    我知道这根本不是你的要求,但你不是在这么做吗?

    public class Dictionary {
        private static final Set<String> WORDS = new HashSet<String>();
    
        public static void add(final String... STRINGS) {
            for (String str : STRINGS) {
                WORDS.add(str.toUpperCase());
            }
        }
    
        public static boolean is(final String STRING) {
            return WORDS.contains(STRING.toUpperCase());
        }
    }
    

        9
  •  1
  •   David Johnstone    17 年前

    switch 语句应该使用哈希来选择要转到哪个case。从那里开始,如果没有,每个后续case也将运行 break 声明。例如,对于你的代码,如果你打开X,它会立即转到X,然后是Y,然后是Z Java Tutorial .

        10
  •  1
  •   David Moles paddy-p    17 年前

    switch if 线性,假设编译器找不到任何聪明的东西。但很长 开关 es很难阅读,也很容易出错——如前所述,你上面的开关没有任何中断,它会在所有情况下都失败。

    为什么不预先填充a Map Map.get() ?

    private static final Map<Char, Whatever> BRANCHES = Collections.unmodifiableMap(new HashMap<Char, Whatever>() {{
        put('A', BRANCH.A);
        ...
        put('Z', BRANCH.Z);
    }}
    
    public void getBranch(char[] WORD, int INDEX) {
        return BRANCHES.get(WORD[INDEX]);
    }
    

    如上所述,如果 BRANCH 是一个 Enum ,此行为应正确地在 .

    (什么是 WORD , INDEX 不管怎样,在这里?从名称上看,它们应该是常量,但你不能真的有常量数组——内容总是可以修改的;创建一个常量“struct”没有多大意义;基于常数进行差分或切换当然没有多大意义。...)

        11
  •  0
  •   Quincy    17 年前

    我认为这更多的是关于风格而不是性能的问题。我认为在这种情况下,switch语句比if语句更合适。我不确定性能是否有太大差异。