Scala 集合中的大小和长度是否生成相同的字节码? [英] Do size and length in Scala collections generate the same byte code?

查看:38
本文介绍了Scala 集合中的大小和长度是否生成相同的字节码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解,根据诸如 等问题,这些方法可能被视为等效"或同义词",尽管并非相同"调用 collection.size 或 collection.lengthScala 缓冲区:大小或长度的最佳 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.lengtharr.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 StringOpsStringOops:

        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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆