【问题标题】:Which combination of switch and if/else is faster and why?switch 和 if/else 的哪个组合更快,为什么?
【发布时间】:2021-01-24 13:16:37
【问题描述】:

我有两组条件。一个有两个可能的值,另一个有更多(在这个例子中,我写了 3 个案例,但最多可能有 8 个)。哪个代码运行速度更快,错误提示更少(更准确)?

代码 a)

if (letter.equals(a)) {
  switch (number) {

    case 1:
           .........
    case 2:
           .........
    case 3:
           .........
  }
} else if (letter.equals(b)) {
  switch (number) {

    case 1:
           .........
    case 2:
           .........
    case 3:
           .........
  }
}

代码 b)

switch (number) {

    case 1:

           if (letter.equals(a)) {
              .........
           } else if (letter.equals(b)) {
              .........
           }

    case 2:

           if (letter.equals(a)) {
              .........
           } else if (letter.equals(b)) {
              .........
           }

    case 3:

           if (letter.equals(a)) {
              .........
           } else if (letter.equals(b)) {
              .........
           }
  }

如果您认为除了这两个之外还有更好的选择,请告诉我。 (我还可以创建一个同时获取 letternumber 的参数,并使用它创建 6 个案例。)

提前谢谢你!

【问题讨论】:

  • 这是基于意见的 .. 但我更喜欢 a)。
  • 当您考虑它时,在这两种结构中您都必须通过 if/else 并恰好切换一次。性能在这里并不重要。

标签: java if-statement switch-statement compiler-optimization


【解决方案1】:

哪个代码运行速度更快,错误提示更少(更准确)?

回答:在这种特定情况下,性能不是问题。因为无论你打算如何使用这个实际的执行次数都是一样的。但是您可以提高代码的可读性并使其不易出错。

与其担心性能,不如从SOLID原则入手。你为什么不把这个大方法分解成一些有具体责任的小方法。它将使代码更漂亮,更不容易出错。例如:

方法:

void processA(int number){
switch (number) {

    case 1:
           .........
    case 2:
           .........
    case 3:
           .........
  }
}

void processB(int number){
    
  switch (number) {

    case 1:
           .........
    case 2:
           .........
    case 3:
           .........
  }
}

///
now from the main method you could simply call:


if (letter.equals(a)) {
   // call the method which will process A
   processA(number);
} else if (letter.equals(b)) {
   // call the method which will process A
   processB(number);
}

【讨论】:

    【解决方案2】:

    这是一个可能对您的代码没有影响的微优化示例,因此“哪个更快”在这里并不重要。

    如果您想找出代码库中的特定案例组合中的哪一个,那么您可能需要使用 JMH 之类的基准测试工具来确定哪个更适合您。但除非这段代码在关键路径上,否则不会有任何影响。

    代码需要:

    1. 正确
    2. 可读
    3. 高性能

    专注于 1 和 2 比专注于上一个要好得多。

    在这种特殊情况下,对于 JVM 来说,switch-over-numbers 可能会更快,而 switch-over-expressions 自然会涉及更多的分支跳转。因此,我天真地期望 switch-over-int-followed-by-if 会以相反的方式略微边缘化,但如果没有证据,这将是一种预感,而不是可以依赖的东西。也很可能无论编写什么基准测试都会存在某种缺陷,例如 JVM 会自动将最佳测试用例组合提升到第一个测试,在这种情况下,它不会告诉您您认为它在做什么。

    最终,写它是为了可读性/可维护性而不是性能,直到你能证明这是在热循环上,然后明确地测量它。

    【讨论】:

      【解决方案3】:

      还有一个选择:

          switch (String.format("%1s%1d", letter, number) {
              case "a1": 
                  ...
              case "b1":
                  ...
              case "a2"
                  ...
              case "b2":
                  ...
              case "a3":
                  ...
              case "b3": 
                  ...
          }
      

      更好?也许,也许不是。但它另一种选择......

      【讨论】:

      • 我有点喜欢这个“技巧”,但重要的是要注意它不会提高性能。它用函数调用 + 开关替换了 if/else + 开关。基本上没有区别。
      • 是的,@akuzminykh 我同意:就性能而言,它可能不会更好(但也可能不会更糟)。然而,在可读性方面,它要好得多,特别是如果“'a'或'b'和1、2或3”的简单示例实际上是“'a'、'b'、 'c'、...、'y' 或 'z' 以及 1、2、3、...、49 或 50"!
      猜你喜欢
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      相关资源
      最近更新 更多