В чем разница между ArrayBuffer и Array
Я новичок в scala/java и у меня проблемы с получением разницы между этими двумя.
Читая scala doc, я понял, что ArrayBuffer
сделаны интерактивными (добавление, вставка, добавление и т.д.).
1) В чем принципиальные отличия реализации?
2) Есть ли разница в производительности между этими двумя?
Ответы
Ответ 1
Оба Array
и ArrayBuffer
изменяемы, что означает, что вы можете изменять элементы в определенных индексах: a(i) = e
ArrayBuffer
является изменяемым, Array
нет. Если вы добавите элемент в ArrayBuffer
, он станет больше. Если вы попытаетесь добавить элемент в Array
, вы получите новый массив. Поэтому для эффективного использования Array
вы должны заранее знать его размер.
Array
реализованы на уровне JVM и являются единственным не стираемым родовым типом. Это означает, что они являются наиболее эффективным способом хранения последовательностей объектов - никаких дополнительных издержек памяти, а некоторые операции реализованы как отдельные коды операций JVM.
ArrayBuffer
реализуется с помощью Array
внутри, и при необходимости выделяет новый. Добавление обычно выполняется быстро, если оно не достигает предела и не изменяет размер массива, но он делает это таким образом, что общий эффект ничтожен, поэтому не беспокойтесь. Prepending реализуется как перемещение всех элементов вправо и установка нового в качестве 0-го элемента, и поэтому он медленный. Добавление n элементов в цикл является эффективным (O (n)), добавление их не является (O (n²)).
Array
специализированы для встроенных типов значений (кроме Unit
), поэтому Array[Int]
будет намного более оптимальным, чем ArrayBuffer[Int]
- значения не должны быть помещены в бокс, поэтому использование меньше памяти и меньше косвенности. Обратите внимание, что специализация, как всегда, работает только в том случае, если тип мономорфен - Array[T]
всегда будет помещен в коробку.
Ответ 2
Еще одно отличие состоит в том, что элемент Array создан как on, когда его объявленные, но Array Buffer элементы не создаются, если вы не назначили значения в первый раз.
Например. Вы можете написать Array1(0)="Stackoverflow"
, но не ArrayBuffer1(0)="Stackoverflow"
для присваивания значений в первый раз.
(Array1 = переменная Array и ArrayBuffer1 = переменная ArrayBuffer)
Поскольку, как известно, буферы Array являются повторно значимыми, поэтому элементы создаются при вставке значений в первый раз, а затем вы можете изменять/переназначать их в конкретном элементе.
Массив:
Объявление и присвоение значений Int массиву.
val favNums= new Array[Int](20)
for(i<-0 to 19){
favNums(i)=i*2
}
favNums.foreach(println)
ArrayBuffer:
Объявление и назначение значений Int 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
в первую строку цикла for, это не сработает. Но он отлично работает, если вы объявите его во 2-й или 3-й строке цикла. Поскольку значения, присвоенные уже в первой строке, теперь можно изменять с помощью индекса элемента.
Этот простой одночасовой видеоурок объясняет многое.
https://youtu.be/DzFt0YkZo8M?t=2005
Ответ 3
Используйте массив Массив, если длина массива исправлена и ArrayBuffer, если длина может меняться.
Ответ 4
Еще одно различие заключается в круге ведения и ценностном равенстве
Array(1,2) == Array(1,2) // res0: Boolean = false
ArrayBuffer(1, 2) == ArrayBuffer(1,2) // res1: Boolean = true
Причина различия заключается в ==
маршрутах к .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