数组作为 switch case 的替代品的性能

Performance of arrays as alternative to switch cases

通常,在我在学校遇到的问题中,有些问题希望我们使用 switch cases。虽然为了更短的代码,我总是使用数组作为这种问题的替代方法。

因此,使用 Switch-Statement 的解决方案如下所示:

String day;
int dayNum = n%7; //n is an input

switch(dayNum){

    case 0:
        day = "Sunday";
        break;
    case 1:
        day = "Monday";
        break;
    case 2:
        day = "Tuesday";
        break;
    case 3:
        day = "Wednesday";
        break;
    case 4:
        day = "Thursday";
        break;
    case 5:
        day = "Friday";
        break;
    case 6:
        day = "Saturday";
        break;
}

System.out.println("Today is " + day);

用数组替代的解决方案如下所示:

int dayNum = n%7; //n is an input
String[] day = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

System.out.println("Today is " + day[dayNum]);

第二个例子是我通常喜欢使用的那种代码。

我想问的是,这两种解决方案在内存和时间复杂度方面有何不同?

你写的代码只是开关使用不当。

当满足其中一项(或最好同时满足两项)时,开关就很棒:

  • 您触发的值不是连续的(即 case 384:,然后是 case 30491:,等等。简单的例子是为某个命令打开字符串时。
  • 您要做的是一堆代码(相对于返回单个结果,如此处所示)。

尽管如此,您还以相当复杂的方式编写了 case 块。如果你有一个单独的方法,你可以写:

switch (foo) {
  case 0: return "Sunday";
  case 1: return "Monday";
}

还有(new in..java14?),你也可以这么写:

String dayName = switch(foo) {
  case 0 -> "Sunday";
  case 1 -> "Monday";
  default -> throw new IllegalArgumentException("Unknown day");
};

最后,这段代码不应该存在。因为 java.time.DayOfWeek 已经存在。你彻底重新发明了轮子。

性能

当谈论 7 个元素时,它并不重要。其他因素占主导地位,就这么简单。

作为一般原则(直到数百甚至数千,见脚注!),你的基于数组的代码在你写的时候是线性的原因是唯一 因为 java 不会(目前;未来的 java 更改正在进行中,可能会改变这一点)意识到 'makes' 带有日期名称的字符串数组可以执行一次JVM 引导的生命周期,再也不会;换句话说,这段代码在幕后编译为创建一个具有 7 个槽的新字符串数组,然后将 7 个常量分配给槽(这些常量是对字符串的引用, 计算“每个 VM 生命周期一次”)。

如果将该数组移动到静态字段中,那将消失,并且它们都是 O(1) 性能(相同 'speed' 无论您有 7 天还是 700 万天),因为它们两者都只进行一次查找。没有循环。

重要性能脚注:计算机非常复杂,并且什么都没有就像冯·诺依曼模型。因此,根据常识预测代码的性能通常会使您大错特错。因此,需要牢记 3 条重要规则:

  • 按照全世界的程序员 java 编写代码的方式编写代码,并保持灵活性。 如果 出现性能问题,您可能需要更改应用的相关部分。如果您的代码灵活,这会更容易。 你读到的大多数关于性能的经验法则都会降低你的代码的灵活性,因此很糟糕! - 此外,JVM 优化代码,并且基本上通过成为一个巨大的模式匹配机器来做到这一点,检测它知道如何 运行 的模式。制作此模式匹配优化机器的程序员倾向于编写 java 代码中常用的模式。因此,惯用的 java 代码在实践中往往很快。

  • 没有人可以只看代码就知道它在现实生活中的表现如何,因为它太复杂了。不要相信我的话; 编写 VM 的工程师一直都这么说。如果他们想不通,你就没有任何机会。因此,在考虑让代码性能想法决定您编写代码的方式之前,需要 分析器报告或 JMH 计时结果。请参阅上面的规则:没有这个,最好、最快的代码就是最干净、最灵活、最易于阅读的代码。

  • 唯一的例外是算法复杂性(大 O 表示法)。这是一个复杂的主题(通常是大学水平的信息学和非常重的数学),远远超出了 SO 的答案,但如果您想深入研究,可以找到大量的在线资源。但请注意,大 O 因素通常不会在您获得大量数据之前,请开始控制。例如,在这种情况下,从技术上讲,您的基于数组的代码是 O(n)(因为您在代码中创建数组,每次 运行 它),而开关是 O(1),但是鉴于这里的 n 是 7,那是无关紧要的。在您获得数百个项目之前,它可能不会变得相关。