作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我很好奇 Java 和 Scala 是如何实现字符串开关的:
class Java
{
public static int java(String s)
{
switch (s)
{
case "foo": return 1;
case "bar": return 2;
case "baz": return 3;
default: return 42;
}
}
}
object Scala {
def scala(s: String): Int = {
s match {
case "foo" => 1
case "bar" => 2
case "baz" => 3
case _ => 42
}
}
}
Java 似乎打开哈希码然后进行单个字符串比较:
0: aload_0
1: dup
2: astore_1
3: invokevirtual #16 // Method java/lang/String.hashCode:()I
6: lookupswitch { // 3
97299: 40
97307: 52
101574: 64
default: 82
}
40: aload_1
41: ldc #22 // String bar
43: invokevirtual #24 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
46: ifne 78
49: goto 82
52: aload_1
53: ldc #28 // String baz
55: invokevirtual #24 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
58: ifne 80
61: goto 82
64: aload_1
65: ldc #30 // String foo
67: invokevirtual #24 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
70: ifne 76
73: goto 82
76: iconst_1
77: ireturn
78: iconst_2
79: ireturn
80: iconst_3
81: ireturn
82: bipush 42
84: ireturn
相比之下,Scala 似乎可以与所有情况进行比较:
0: aload_1
1: astore_2
2: ldc #16 // String foo
4: aload_2
5: invokevirtual #20 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
8: ifeq 16
11: iconst_1
12: istore_3
13: goto 47
16: ldc #22 // String bar
18: aload_2
19: invokevirtual #20 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
22: ifeq 30
25: iconst_2
26: istore_3
27: goto 47
30: ldc #24 // String baz
32: aload_2
33: invokevirtual #20 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
36: ifeq 44
39: iconst_3
40: istore_3
41: goto 47
44: bipush 42
46: istore_3
47: iload_3
48: ireturn
是否有可能说服 Scala 使用哈希码技巧?我宁愿选择 O(1) 解决方案而不是 O(n) 解决方案。在我的真实代码中,我需要与 33 个可能的关键字进行比较。
最佳答案
显然,这种情况似乎是缺乏 Scala 编译器的优化。当然,match
构造比 Java 中的 switch/case 强大得多(多得多),并且优化它要困难得多,但它可以检测到这些特殊情况,在这些特殊情况下进行简单的哈希比较会适用。
另外,我不认为这种情况会在惯用的 Scala 中出现很多次,因为您总是匹配除了具有不同值之外还有一些意义的案例类。
关于java - 打开弦乐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29355328/
我在 Rails 应用程序中有一个花哨的“工作表”样式 View ,加载时间太长。 (在开发模式下,是的,我知道那里没有缓存,“在 57893 毫秒内完成(查看:54975,DB:855)”)工作表是
我是一名优秀的程序员,十分优秀!