Scala 集合中的大小和长度是否生成相同的字节码? [英] Do size and length in Scala collections generate the same byte code?
问题描述
我了解,根据诸如 等问题,这些方法可能被视为等效"或同义词",尽管并非相同"调用 collection.size 或 collection.length 和 Scala 缓冲区:大小或长度的最佳 Scala 约定是什么?.
I understand that these methods may be considered "equivalent" or "synonyms", albeit not "identical", according to questions such as Is the best Scala convention to invoke collection.size or collection.length and Scala Buffer: Size or Length?.
但这是否意味着它们是相同的?
But does that mean they are the same?
不要向我提供意见或一厢情愿的相同概念.当它们实际上不一样时告诉我.
Don't offer me opinions or wishy-washy notions of sameness. Just tell me when they're not actually the same.
用硬科学来支持你的主张!
Back up your claim with hard science!
字节码就足够了.我对特定于 JIT 的优化不太感兴趣.
Byte code will suffice. I'm not so interested in JIT-specific optimizations.
我对世界的当前状态特别感兴趣,即最近里程碑中的 Scala 2.11.
I'm especially interested in the current state of the world, namely, Scala 2.11 in recent milestones.
推荐答案
String 和 Array 仍然在 2.11 中包装尺寸.
String and Array are still wrapped for size in 2.11.
你应该训练你的手指输入s.length
和arr.length
.
You should train your fingers to type s.length
and arr.length
.
这并不难,因为字符串和数组都有长度.
That's not hard, because both strings and arrays have length.
从 Java 来到 Scala 的人通常会决定是使用 java.lang.String
上的方法还是方便的扩充.因为在我们被要求 从休息室用甜甜圈补充,作为政策问题,值得提前做出一些决定.
Someone coming to Scala from Java will often decide whether to use the methods on java.lang.String
or the convenient augmentations. Since we have a finite "decision budget" before we are required to replenish it with donuts from the break room, it's worth making a few of these decisions up front as a policy matter.
如果人们在午餐或甜甜圈上没有更好的讨论:
In case one has nothing better to discuss at lunch, or over donuts:
22: invokevirtual #41 // Method scala/Predef$.augmentString:(Ljava/lang/String;)Ljava/lang/String;
25: invokespecial #44 // Method scala/collection/immutable/StringOps."<init>":(Ljava/lang/String;)V
28: invokevirtual #47 // Method scala/collection/immutable/StringOps.size:()I
18: invokevirtual #39 // Method scala/Predef$.intArrayOps:([I)Lscala/collection/mutable/ArrayOps;
21: invokeinterface #44, 1 // InterfaceMethod scala/collection/mutable/ArrayOps.size:()I
等等,等等,使用 -optimise 你可能会丢失 AugmentString.
Wait, wait, with -optimise you can lose the augmentString.
GenSeqLike
引入了 length
并指定它产生与 size
相同的结果".SeqLike
就是这样实现的.
It's GenSeqLike
that introduces length
and specifies that it "yields the same result" as size
. SeqLike
implements it that way.
实际上,String
是通过对SeqLike
的扩充来获取size
方法的,具体来说,就是StringLike
.这需要包装.事实上,预测哪些调用需要包装或分派到扩展方法并不容易.
In fact, String
acquires a size
method by augmentation to a SeqLike
, specifically, StringLike
. That requires wrapping. In fact, it's not easy to predict which calls require wrapping, or dispatch to an extension method.
例如,length
是以不需要包装的方式定义的.那是因为 StringOps
是一个值类.事实上,它编译为String.length
.
For instance, length
is defined in a way that wrapping is not required. That's because StringOps
is a value class. In fact, it compiles to String.length
.
然而,StringOps
上的 apply
方法,定义为调用 charAt
来模拟数组 apply,虽然定义方式相同, 调用扩展方法.
However, the apply
method on StringOps
, defined as a call to charAt
to mimic an array apply, though defined in the same way, calls the extension method.
(当然,在 JIT 编译之后,一些操作码和分配可能没有多大意义.)
(A few opcodes and allocations may not mean much after JIT compilation, of course.)
scala> val s = "hello"
s: String = hello
scala> val n = s.length ; val i = s.size ; val c = s(4) ; s.slice(0,4)
n: Int = 5
i: Int = 5
c: Char = o
res0: String = hell
scala> :javap -prv -
public $line4.$read$$iw$$iw$();
flags: ACC_PUBLIC
Code:
stack=5, locals=7, args_size=1
0: aload_0
1: invokespecial #32 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #34 // Field MODULE$:L$line4/$read$$iw$$iw$;
8: aload_0
9: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
12: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
长度
:
15: invokevirtual #47 // Method java/lang/String.length:()I
18: putfield #22 // Field n:I
21: aload_0
new StringOps
或 StringOops
:
22: new #49 // class scala/collection/immutable/StringOps
25: dup
26: getstatic #54 // Field scala/Predef$.MODULE$:Lscala/Predef$;
29: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
32: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
35: astore_2
36: astore_1
37: aload_2
StringOps.size
:
38: invokespecial #57 // Method scala/collection/immutable/StringOps."<init>":(Ljava/lang/String;)V
41: invokevirtual #60 // Method scala/collection/immutable/StringOps.size:()I
44: putfield #25 // Field i:I
47: aload_0
48: getstatic #65 // Field scala/collection/immutable/StringOps$.MODULE$:Lscala/collection/immutable/StringOps$;
51: getstatic #54 // Field scala/Predef$.MODULE$:Lscala/Predef$;
54: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
57: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
60: astore 4
62: astore_3
63: aload 4
65: iconst_4
apply
扩展方法:
66: invokevirtual #69 // Method scala/collection/immutable/StringOps$.apply$extension:(Ljava/lang/String;I)C
69: putfield #28 // Field c:C
72: aload_0
73: getstatic #65 // Field scala/collection/immutable/StringOps$.MODULE$:Lscala/collection/immutable/StringOps$;
76: getstatic #54 // Field scala/Predef$.MODULE$:Lscala/Predef$;
79: getstatic #39 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
82: invokevirtual #42 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
85: astore 6
87: astore 5
89: aload 6
91: iconst_0
92: iconst_4
和切片
:
93: invokevirtual #73 // Method scala/collection/immutable/StringOps$.slice$extension:(Ljava/lang/String;II)Ljava/lang/String;
96: putfield #31 // Field res0:Ljava/lang/String;
99: return
这篇关于Scala 集合中的大小和长度是否生成相同的字节码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!