我是scala/java的新手,我有些困惑,不知道这两者之间有什么区别。
通过阅读scala 文档,我了解到ArrayBuffer
的设计目的是可互动操作(追加,插入,前置等)。
1)它们之间的基本实现差异是什么?
2)它们之间是否存在性能差异?
Array
和ArrayBuffer
都是可变的,这意味着您可以修改特定索引处的元素:a(i) = e
ArrayBuffer
是可调整大小的,Array
则不是。如果您向ArrayBuffer
附加一个元素,它会变大。如果您尝试将一个元素附加到Array
中,则会得到一个新的数组。因此,要有效地使用Array
,必须事先知道其大小。
Array
在JVM级别上实现,并且是唯一的非擦除通用类型。这意味着它们是存储对象序列的最有效方式 - 没有额外的内存开销,并且一些操作被实现为单个JVM操作码。
ArrayBuffer
通过在内部拥有一个Array
并在需要时分配一个新的来实现。附加通常很快,除非它达到限制并调整数组大小 - 但它以一种使总体效果可以忽略不计的方式进行,因此不用担心。预先添加是通过将所有元素移动到右侧并将新元素设置为第0个元素来实现的,因此速度较慢。在循环中附加n个元素是高效的(O(n)),但预先添加这些元素则不是(O(n²))。
Array
对于内置值类型(除Unit
之外)进行了专门化处理,因此Array[Int]
比ArrayBuffer[Int]
更加优化 - 值不必被装箱,因此使用的内存和间接性较少。请注意,专门化仅在类型是单态时起作用 - Array[T]
将始终被装箱。
Array1(0)=“Stackoverflow”
但不能写ArrayBuffer1(0)=“Stackoverflow”
用于第一次值分配。val favNums= new Array[Int](20)
for(i<-0 to 19){
favNums(i)=i*2
}
favNums.foreach(println)
声明并分配整数ArrayBuffer的值。
val favNumsArrayBuffer= new ArrayBuffer[Int]
for(j<-0 to 19){
favNumsArrayBuffer.insert(j, (j*2))
//favNumsArrayBuffer++=Array(j*3)
}
favNumsArrayBuffer.foreach(println)
favNumsArrayBuffer(j)=j*2
,它将无法正常工作。但是如果你在循环的第二或第三行声明它,那么它就可以正常工作了。因为在第一行已经分配了值,现在你可以通过元素索引进行修改。如果数组长度固定,请使用Array,如果长度可变,请使用ArrayBuffer。
:+=
可以在 Array
上工作?这个答案如何改进或补充了 @KarolS 的更详细的答案? - jwvh另一个区别在于引用和值的相等性。
Array(1,2) == Array(1,2) // res0: Boolean = false
ArrayBuffer(1, 2) == ArrayBuffer(1,2) // res1: Boolean = true
==
routes 到 .equals
的转换,其中Array.equals
是使用Java的==
实现的,它比较引用。public boolean equals(Object obj) {
return (this == obj);
}
当 ArrayBuffer.equals
比较 ArrayBuffer
中包含的元素时,使用 sameElements
方法。
override def equals(o: scala.Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (
o match {
case it: Seq[A] => (it eq this) || (it canEqual this) && sameElements(it)
case _ => false
}
)
同样, contains
的行为有所不同
Array(Array(1,2)).contains(Array(1,2)) // res0: Boolean = false
ArrayBuffer(ArrayBuffer(1,2)).contains(ArrayBuffer(1,2)) // res1: Boolean = true