Почему только один новый объект создается при многократном вызове в `map`? - PullRequest
0 голосов
/ 17 октября 2019

Насколько я понимаю, способ создания нового ArrayBuffer с одним элементом - это сказать

val buffer = ArrayBuffer(element)

или что-то вроде этого:

val buffer = ArrayBuffer[Option[String]](None)

Предположим, xэто коллекция с 3 элементами. Я пытаюсь создать карту, которая создает новый 1-элемент ArrayBuffer для каждого элемента в x и связывает элемент в x с новым буфером. (Это намеренно отдельные изменяемые буферы, которые будут изменены потоками.) Я попробовал это:

x.map(elem => (elem, ArrayBuffer[Option[String]](None))).toMap

Однако я обнаружил (используя System.identityHashCode), что был создан только один ArrayBuffer, и все 3элементы были сопоставлены с одинаковым значением.

Почему это происходит? Я ожидал, что выражение кортежа будет оцениваться для каждого элемента x, и это приведет к созданию нового ArrayBuffer для каждой оценки выражения.

Что будет хорошим обходным решением?

Я использую Scala 2.11.

Обновление

В процессе создания воспроизводимого примера я разобрался с проблемой. Вот пример;Source - это интерфейс, определенный в нашем приложении.

  def test1(x: Seq[Source]): Unit = { 
    val containers = x.map(elem => (elem, ArrayBuffer[Option[String]](None))).toMap
    x.foreach(elem => println(
      s"test1: elem=${System.identityHashCode(elem)} container=${System.identityHashCode(containers(elem))}"))
    x.indices.foreach(n => containers(x(n)).update(0, Some(n.toString)))
    x.foreach(elem => println(s"resulting value: ${containers(elem)(0)}"))
  }

Что я пропустил, так это то, что для значений x, которые я пытался использовать, класс, реализующий Source, возвращал true для equals() для всех комбинаций значений. Таким образом, полученная карта имела только одну пару ключ-значение.

Извините, что не выяснил это раньше. Я удалю вопрос через некоторое время.

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Я не могу воспроизвести проблему, например

val m = 
  List(Some("a"), Some("b"), Some("c"))
    .map(elem => (elem, ArrayBuffer[Option[String]](None)))
    .toMap

m(Some("a")) += Some("42")

m

output

res2: scala.collection.immutable.Map[Some[String],scala.collection.mutable.ArrayBuffer[Option[String]]] = Map(
  Some(a) -> ArrayBuffer(None, Some(42)), 
  Some(b) -> ArrayBuffer(None), 
  Some(c) -> ArrayBuffer(None)
)

, где мы видим, что Some("42") был добавлен в один буфер, в то время как другие не были затронуты.

1 голос
/ 17 октября 2019

Я думаю, что ваша проблема - toMap. Если все три элемента None, то у вас на карте только один элемент (так как все имеют один и тот же ключ).

Я немного играл на Scalafiddle (удалите .toMapи у вас будет 3 ByteArrays)

, дайте мне знать, если я вас неправильно понял.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...