在Java中切换语句与Ifs

时间:2014-09-11 14:31:03

标签: java

Herbert Schildt" The Complete Reference " - 第5章:

  

switch语句通常比一组嵌套ifs更有效。

     

当编译器编译switch语句时,它会检查每个case常量并创建一个" Jump Table"它将用于根据表达式的值选择执行路径。因此,如果需要在一大组值中进行选择,则switch语句的运行速度将比使用if-elses序列编码的等效逻辑快得多。编译器可以这样做,因为它知道case常量都是相同的类型,并且必须与switch表达式进行相等性比较。编译器不知道if表达式的长列表。

  1. 他的意思是" JUMP TABLE "?

  2. Switch不同于if - 语句,switch只能测试是否相等,而if可以评估任何类型的boolean表达式。如果switch(expression)与任何案例常量都不匹配,则意味着它进入default案例。这不是一个不平等的案例吗?这让我想到switchif之间没有这么大的区别。

  3. 从同一本书的摘录中,他写道:

      

    if-then-else语句可以根据值或条件的范围测试表达式,而switch语句只根据单个整数,枚举值或String对象测试表达式。

    不会使ifswitch更强大吗?

  4. 我曾在Core Java的不同项目中工作,但从未觉得需要使用switch语句,也没有看到其他同事使用它。甚至没有一次。为什么更强大的switch控制语句在可用性方面无法在if之前登陆?

5 个答案:

答案 0 :(得分:5)

1)编译器为每个case语句创建一个包含行的表,其中case条件是键,代码块是值。在代码中执行switch语句时,可以通过案例块的键直接访问案例块。在嵌套if块中,您需要检查并执行每个条件,然后才能找到输入条件代码块的正确条件。

将其视为哈希表(对于switch case)与线性链表(对于嵌套的if语句)进行比较,并比较查找特定值的时间。表的查找时间为O(1)(只需在一次操作中获取),其中链表中的查找时间为O(n)(查看每个项目,直到找到正确的项目)。

3)是的,if语句可以更灵活地使用并表达更多,但是如果你想在不同的代码块之间切换以获得不同值的列表a {{ 1}}块执行得更快,更易读。

4)你从不需要来使用switch,因为嵌套的switch可以表达相同的内容,但在某些情况下它更优雅。但由于很少使用它,程序员会忘记它,即使在适合它的地方也不要使用它。

2)从其他点的答案中提取差异。

答案 1 :(得分:3)

我一直使用switch,如果你没有使用它,那你就错误地做了Java。

跳转表可以被认为是代码中的位置数组。例如,想象一下:

case 0:
   // do stuff
   break;
case 1:
   // do stuff 2
   break;
case 3:
   // do stuff 3
   break;

然后你有一个只包含

的跳转表
codeLocations[] = { do stuff, do stuff 2, do stuff 3 }.

然后为案例1找到正确的代码位Java只需要转到codeLocations[1]。不需要实际的整数比较。

显然,实际的实现比这更复杂,因为它需要处理更多不同的案例,但它提出了这个想法。

ifswitch都不比彼此更强大。它们都是工具。你问的是锤子是否比螺丝刀更强大。是的,锤子会把更多东西撞到木头上,但是如果你使用螺丝钉,螺丝刀会做得更好:)

扩展"做java错误"事情:

Switch是Java语言中的一个工具,由于某种原因而被添加。

您可以将完全相同的问题应用于for循环。您可以使用for循环执行的所有操作也可以使用while循环(尽管可能需要编写更多代码)。尝试一下。

这不会使while更强大"甚至更有用"比for。它们是不同的工具,具有不同的优点和缺点。

switchifforwhile相同。他们做类似的工作,在很多地方你也可以使用。然而,有一个明显的例子,其中一个优于另一个。

如果您使用某种语言进行编程而忽略该语言工具包中的一个基本工具,那么您使用的语言就是错误的。这不是一个几乎不被使用的模糊特征,这是该语言中的主要流控制语句之一。

如果木匠只使用锤子而且从不使用螺丝刀......他们做错了。同样,如果程序员从不使用重要的语言功能......他们做错了。

这里有一句谚语"如果你拥有的唯一工具是锤子,那么所有东西看起来都像是钉子"

答案 2 :(得分:2)

1:跳转表是一个跳跃目标表。跳转目标是代码中的地址,其对应于属于交换机中的情况的代码。如果你的交换机情况是一个简单的例子,0,1,...... N,那么N + 1个目标将分别位于表的索引0,1,... N处。您只需计算您开启的值,然后通过索引到表中查找目标,而不是通过比较N + 1次。这就是效率。

2:default是一个不平等的案例,是的,但非常有限,正如你所注意到的那样。它的情况是"不等于任何其他情况"但它不能低于给定值"或者"大于......"

3:是的,if更强大。但是,switch有时会更有效率。效率!=力量。

4:力量!=效率。但是,要回答隐含的问题:未使用更高效的switch语句,因为您的同事没有使用它。你必须问他们为什么。也许这只是一种品味,或者是对switch的优势的无知。 switch语句的更高效率几乎总是不会引起注意,除非你处于一个性能敏感的环境中,所以人们通常不会意识到它。如果性能不是最重要的,那么可读性就是。在某些情况下,开发人员可能会考虑使用switch语句并确定一系列if语句更易于阅读和理解。

答案 3 :(得分:2)

1)在切换情况下,跳转表将代码段中的位置映射到特定情况。例如,考虑这个片段:

int a;
// a is manipulated here
switch (a) {
    case 1: // address 0
        // ...
        break;
    case 2: // address 1
        // ...
        break;
    case 3: // address 2
        // ...
        break;
    default: // other cases
        // ...
        break;
}

会有一个跳转表,将a = 1映射到由address 0标记的有效代码地址,a = 2到address 1,依此类推。在观察结果字节码时,这会变得更加明显。使用这种方法,字节码中条件跳转的数量变得比if-else语句的小得多。

2)if-else语句确实可以测试不等式,但是实现switch-case语句的相同行为涉及链接if-else语句。以下是行为方面的上述等效版本。

if (a==1) {
    // ...
} else if (a==2) {
    // ...
} else if (a==3) {
    // ...
} else {
  // for any other cases
}

在某些情况下,这可能是个人意见问题,但在这种特殊情况下,switch-case语句更具可读性。 但很自然地,if-else语句仍然是不可或缺的,并且您应该使用正确的工具来完成工作。 If-elseswitch-case更通用,但后者可能会在某些地方产生更好的代码。希望这能回答你问题的第3和第4部分。

答案 4 :(得分:0)

在外行人看来,差异可以忽略不计。

两者都有专业人士缺点。在大多数情况下,您从不使用切换 - 而是将 hashmap 或其他一些的操作结合使用更好的可读性

我建议您阅读Efficient Java或https://code.google.com/p/guava-libraries/wiki/GuavaExplained

在c#中你可以这样写:

class MyClass
{
    static Dictionary<string, Func<MyClass, string, bool>> commands
        = new Dictionary<string, Func<MyClass, string, bool>>
    {
        { "Foo", (@this, x) => @this.Foo(x) },
        { "Bar", (@this, y) => @this.Bar(y) }
    };

    public bool Execute(string command, string value)
    {
        return commands[command](this, value);
    }

    public bool Foo(string x)
    {
        return x.Length > 3;
    }

    public bool Bar(string x)
    {
        return x == "";
    }
}

之后你可以

var item = new MyClass();
item.Execute("Foo","ooF");