Java:枚举与 if-then-else 的性能对比

发布于 2024-10-16 03:54:09 字数 186 浏览 10 评论 0原文

我没有真正幸运地通过使用谷歌获得这个比较的简洁答案,我想我应该先问一下,而不是自己做耗时的评估。

我相当确定使用枚举的 switch 语句比 if-then-else 语句执行得更快,尽管它是否存在显着差异是另一个问题。

有人可以帮我解释一下吗?


感谢大家的快速回复,我会在未来的项目中牢记这一点。

I've had no real luck getting a concise answer for this comparison by using Google and rather than do my own time consuming evaluations, I thought I would ask first.

I'm fairly sure that a switch statement using Enums would perform faster than an if-then-else statement, though whether or not it is a noticable difference is another question.

Could someone shed some light on this for me?


Thanks for the quick responses guys, I will keep this in mind for future projects.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

浪荡不羁 2024-10-23 03:54:09

是的,确实如此,因为一般来说 switch 语句比 if/else 链运行得更快。

尽管生成的字节码并不总是性能比较的明确来源,但您可以检查它以获得更好的想法。

例如这段代码:

class A { 
    enum N { ONE, TWO, THREE }
    void testSwitch( N e ) { 
        switch( e ) { 
            case ONE : x(); break;
            case TWO : x(); break;
            case THREE : x(); break;
        }
    }
    void testIf( Enum e ) { 
        if( e == N.ONE ) { x(); }
        else if( e == N.TWO ) { x(); }
        else if( e == N.THREE ) { x(); }
    }
    void x(){}
}

生成以下内容:

Compiled from "A.java"
class A extends java.lang.Object{
A();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

void testSwitch(A$N);
  Code:
   0:   getstatic   #2; //Field A$1.$SwitchMap$A$N:[I
   3:   aload_1
   4:   invokevirtual   #3; //Method A$N.ordinal:()I
   7:   iaload
   8:   tableswitch{ //1 to 3
        1: 36;
        2: 43;
        3: 50;
        default: 54 }
   36:  aload_0
   37:  invokevirtual   #4; //Method x:()V
   40:  goto    54
   43:  aload_0
   44:  invokevirtual   #4; //Method x:()V
   47:  goto    54
   50:  aload_0
   51:  invokevirtual   #4; //Method x:()V
   54:  return

void testIf(java.lang.Enum);
  Code:
   0:   aload_1
   1:   getstatic   #5; //Field A$N.ONE:LA$N;
   4:   if_acmpne   14
   7:   aload_0
   8:   invokevirtual   #4; //Method x:()V
   11:  goto    39
   14:  aload_1
   15:  getstatic   #6; //Field A$N.TWO:LA$N;
   18:  if_acmpne   28
   21:  aload_0
   22:  invokevirtual   #4; //Method x:()V
   25:  goto    39
   28:  aload_1
   29:  getstatic   #7; //Field A$N.THREE:LA$N;
   32:  if_acmpne   39
   35:  aload_0
   36:  invokevirtual   #4; //Method x:()V
   39:  return

void x();
  Code:
   0:   return

}

在这两种情况下似乎都非常快。

因此,选择一个更容易维护的。

Yeap, it does, because in general term a switch statement works faster than if/else chain.

Although bytecode generated is not always definitive source for performance comparisons you can examine it to have a better idea.

For instance this code:

class A { 
    enum N { ONE, TWO, THREE }
    void testSwitch( N e ) { 
        switch( e ) { 
            case ONE : x(); break;
            case TWO : x(); break;
            case THREE : x(); break;
        }
    }
    void testIf( Enum e ) { 
        if( e == N.ONE ) { x(); }
        else if( e == N.TWO ) { x(); }
        else if( e == N.THREE ) { x(); }
    }
    void x(){}
}

Generates the following:

Compiled from "A.java"
class A extends java.lang.Object{
A();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

void testSwitch(A$N);
  Code:
   0:   getstatic   #2; //Field A$1.$SwitchMap$A$N:[I
   3:   aload_1
   4:   invokevirtual   #3; //Method A$N.ordinal:()I
   7:   iaload
   8:   tableswitch{ //1 to 3
        1: 36;
        2: 43;
        3: 50;
        default: 54 }
   36:  aload_0
   37:  invokevirtual   #4; //Method x:()V
   40:  goto    54
   43:  aload_0
   44:  invokevirtual   #4; //Method x:()V
   47:  goto    54
   50:  aload_0
   51:  invokevirtual   #4; //Method x:()V
   54:  return

void testIf(java.lang.Enum);
  Code:
   0:   aload_1
   1:   getstatic   #5; //Field A$N.ONE:LA$N;
   4:   if_acmpne   14
   7:   aload_0
   8:   invokevirtual   #4; //Method x:()V
   11:  goto    39
   14:  aload_1
   15:  getstatic   #6; //Field A$N.TWO:LA$N;
   18:  if_acmpne   28
   21:  aload_0
   22:  invokevirtual   #4; //Method x:()V
   25:  goto    39
   28:  aload_1
   29:  getstatic   #7; //Field A$N.THREE:LA$N;
   32:  if_acmpne   39
   35:  aload_0
   36:  invokevirtual   #4; //Method x:()V
   39:  return

void x();
  Code:
   0:   return

}

Which seems to be pretty fast in both cases.

So, pick the one that is easier to maintain.

懵少女 2024-10-23 03:54:09

只要坚持使用你能想到的最易读和最清晰理解的代码,我相信你在寻找这个答案时已经失去了在性能优化中获得的所有时间。像这样的微观优化很少是值得的,并且很容易导致代码比需要的更复杂。

Just stick with the most readable and clear to understand code you can come up with, I'm sure you lost all the time gained in the performance optimization while looking for this answer already. Micro-optimizations like this rarely are worth it and can easily result in code that's more complex than needed.

万劫不复 2024-10-23 03:54:09

我不知道更快,我猜他们都快得惊人。

我的考虑是,带有枚举的 switch 比多个 if/else 块更具可读性

,但要小心丢失的break语句!

I don't know about faster, I'd guess they are both blazingly fast.

My consideration is that switch with enums is a lot more readable than a multi-if/else block

But beware of missing break statements!!

洋洋洒洒 2024-10-23 03:54:09

是的,switch 语句几乎总是比 if / else 语句的等效块执行得更快,因为编译器可以执行更多优化(通常 switch 块被编译为分支表,这几乎不可能用 if / else 语句块来完成)条件。)

我想说它们也更具可读性和更可维护性(除了使用我建议反对的失败案例!)至于

它是否明显更快,这取决于您定义的显着性。除非你追求的是非常具体的东西,否则你根本不会注意到它,但我仍然会这样做,因为可读性优势比其他任何东西都重要(将速度优势视为奖励!)

Yes, a switch statement will pretty much always execute faster than the equivalent block of if / else statements because the compiler can perform more optimisations (typically a switch block becomes compiled down to a branch table which is pretty much impossible to do with a block of conditionals.)

I'd say they're also both more readable and more maintainable (with the exception of using fall-through cases which I'd advise against!)

As to whether it's noticeably faster, it depends what you define as noticeable. Chances are unless you're after something really specific you won't notice it at all, but I'd still do things this way because of the readability advantage more than anything else (treat the speed advantage as a bonus!)

尬尬 2024-10-23 03:54:09

我对此的回答与往常的问题相同,即语言构造 X 通常比语言构造 Y 更快:没有通用答案!

对于某种语言的某些实现,可能只有具体的答案,例如 Oralce(以前是 Sun 的)基于 JVM 的 Hotspot 编译器,或者平台 Z 上的 IBM JDK 或 Linux 上的 OpenJDK,或者……

所以,给出的唯一方法对你的问题的一个有意义的答案是进行适当的基准测试。请注意微基准测试,它们通常是错误的而不是正确的,请参见例如 如何不编写微基准基准。如果您仍然想找到有关使用此问题框架描述的此处

因此,我建议根据您的上下文的适用性和可读性来选择语言功能。

My answer to this is the same as always to question is language construct X generally faster than language construct Y: There is no general answer!

There may be only specific answer for certain implementations of a language, e.g. Oralce's (formally Sun's) Hotspot-compiler based JVM or for an IBM JDK on plattform Z or for an OpenJDK on Linux, or...

So, the only way to give a meaningfull answer to your question is to do a proper benchmark. Beware of micro benchmarks, they are more often wrong than right, see e.g. How not to write a micro benchmark. If you still want to find about use this question framework described here.

Therfore, I would advise to select language feature by their applicability and readibility in your context.

笑梦风尘 2024-10-23 03:54:09

理论上,switch 语句可以优化为单个计算跳转,而 if-then-else 链必须保留为单独的比较。我不知道 Java 是否真的执行了这种优化。

无论如何,开关在可读性和可维护性方面都比 if-then-else 链更好,所以如果可能的话无论如何都要使用它们。

In theory a switch statement can be optimised as a single calculated jump, whereas if-then-else chains have to remain as individual comparisons. I don't know whether Java actually performs this optimisation though.

Regardless, switches are better than if-then-else chains in terms of readability and maintainability, so use them anyway if possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文