Карта с ошибкой пустого ListBuffer в scala - PullRequest
5 голосов
/ 22 марта 2012

Я пытаюсь создать изменяемый Map со значением по умолчанию, которое создает новый ListBuffer, когда запрашивается элемент, которого еще нет на карте.Однако, хотя новая карта возвращается по умолчанию, она не остается на карте.Может быть, это именно то, как это работает, подумал я, но когда я протестировал его с Int, а не ListBuffer, все получилось именно так, как я хотел.Вот некоторый код, объясняющий, что я имею в виду - что я делаю неправильно?

Во-первых, здесь он работает с Map[Int]:

scala> val a = collection.mutable.Map(1 -> 1).withDefault(i => 0)
a: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1)

scala> a(1) += 1 // adding to an existing element works as expected

scala> a
res48: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> a(2) += 1 // what about adding to a non-existing element?

scala> a // the new element has been added to the map
res50: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2, 2 -> 1)

Теперь с Map[ListBuffer[Int]]:

scala> val b = collection.mutable.Map(1 -> collection.mutable.ListBuffer[Int]()).withDefault(i => collection.mutable.ListBuffer.empty[Int])
b: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer())

scala> b(1) += 1 // appending to an existing element works as expected
res51: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)

scala> b
res52: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer(1))

scala> b(2) += 1 // but appending to a non-existing element...
res53: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)

scala> b // leaves the map unchanged
res54: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer(1))

Ответы [ 2 ]

3 голосов
/ 22 марта 2012

Разница заключается в следующем:

В первом случае a(2) - это Int. Поскольку Int не имеет метода +=, a(2) += 1 эквивалентен a(2) = a(2) + 1 и, следовательно, a.update(2, a(2) + 1). update фактически меняет карту.

Но ListBuffer[Int] имеет метод +=, поэтому ваш вызов a(2).+=(1), и вы не устанавливаете a(2) для чего-либо!

1 голос
/ 23 марта 2012

Вы можете использовать getOrElseUpdate(key: A, op: => B), где вы можете просто создать новый экземпляр ListBuffer, когда ключ отсутствует.

Е.Г.

val m = collection.mutable.Map[Int, ListBuffer[Int]]()
m.getOrElseUpdate(1, ListBuffer()) += 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...