В чем разница между 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