Проблемы с добавлением объектов в ListBuffer в Scala

У меня проблемы с добавлением объектов в scala.collection.mutable.ListBuffer. Я знаком с соответствующим API и знаю, что обычно вы используете метод + = или ++ = для добавления объекта или последовательности объектов.

Я реализую карточную игру с поддержкой сети, и у меня возникла простая проблема - добавить несколько выбранных карт в список ручных карт . В следующем коде я собираюсь получить ссылку на Список карточек (ListBuffer), распечатать размер ListBuffer, добавить к нему выбранные карточки и снова распечатать размер.

// get the references and ensure that it are rally ListBuffers / Lists
val handCards: mutable.ListBuffer[ClientCard] = playerPanel.player.handCards
val chosenCards: List[ClientCard] = _chosenCards

// print the number of elements per list
println("number of hand cards: " + handCards.size)
println("number of chosen cards: " + chosenCards.size)

// append the chosen cards to the hand cards
println("append operation: " + handCards + " ++= " + chosenCards)
handCards ++= chosenCards

// print the number of hand cards again
println("number of hand cards: " + handCards.size)

В результате можно ожидать, что размер карточек будет увеличиваться в зависимости от размера выбранных карточек. Но вывод (форматированный):

number of hand cards: 5
number of chosen cards: 2

append operation: ListBuffer(
    [email protected], 
    [email protected], 
    [email protected], 
    [email protected], 
    [email protected]
) ++= List(
    [email protected], 
    [email protected]
)

number of hand cards: 5

Таким образом, элементы не были добавлены.

ClientCard всегда является представителем «реальной карты» и состоит только из информации, необходимой для извлечения карты.

trait ClientCard extends AnyRef with ClientObject with CardLike

trait ClientObject extends Serializable {
    def uid: Int
}

trait CardLike {
    val imagePath: String
}

ClientCard создается в классе Card:

def clientCard = new ClientCard() {
    val uid = Card.this.hashCode()
    val imagePath = CardTemplate.cardFolder + Card.this.imageFilename
}

И есть ClientPlayer (представитель «реального игрока»), где создается ListBuffer:

// definition of ClientPlayer trait
trait ClientPlayer extends ClientObject {
    val victoryPoints: Int
    val handCards: mutable.ListBuffer[ClientCard] 
    val playedCards: mutable.ListBuffer[ClientCard]
}

// piece of code to create a client player
def clientPlayer = new ClientPlayer() {
    val uid = Player.this.hashCode()
    val victoryPoints = Player.this.victoryPoints

    val handCards = new mutable.ListBuffer[ClientCard]
    handCards ++= (Player.this.handCards.map(_.clientCard)) 

    val playedCards = new mutable.ListBuffer[ClientCard]
    playedCards ++= Player.this.playedCards.map(_.clientCard)
}

Кто-нибудь знает, что здесь происходит не так? Или, чтобы быть более общим: какие существуют обстоятельства, препятствующие успешному добавлению объектов в ListBuffer?

Изменить: Есть кое-что, что я забыл упомянуть, и что, казалось, вызвало это странное поведение. После создания HandBards ListBuffer он отправляется по сети и поэтому снова сериализуется и десериализуется.

После комментария Рекса Керра я попытался создать метод глубокой копии для ClientPlayer и скопировал каждый ClientPlayer сразу после его получения. Это решило проблему. У кого-нибудь есть объяснение этому поведению?

4 голоса | спросил Zwackelmann 13 Jpm1000000pmFri, 13 Jan 2012 20:52:05 +040012 2012, 20:52:05

1 ответ


0

Десериализация приводит к чрезвычайно хрупкому ListBuffer. Это, вероятно, ошибка, но в качестве обходного пути, only , что вам нужно сделать, это немедленно добавить ее в какую-то другую коллекцию (например, с помощью toList или добавив его в пустой ListBuffer).

Вот некоторый код, который вы можете использовать для проверки проблем с сериализацией /десериализацией:

import collection.mutable.ListBuffer
import java.io._
val baos = new ByteArrayOutputStream
val oos = new ObjectOutputStream(baos)
oos.writeObject( ListBuffer(1,2,3) )
val bais = new ByteArrayInputStream( baos.toByteArray )
val ois = new ObjectInputStream(bais)
val lb = ois.readObject.asInstanceOf[ListBuffer[Int]]
val lb2 = ListBuffer[Int]() ++= lb
lb2 ++= List(1)  // All okay
lb ++= List(1)  // Throws an exception for me

Я отправлю сообщение об ошибке, но пока вы не должны полагаться на ListBuffer Быть в разумном состоянии, когда десериализовано, и вместо этого восстановить его. (Возможно, вы захотите сериализовать и десериализовать List.)

ответил Rex Kerr 13 Jpm1000000pmFri, 13 Jan 2012 23:01:42 +040012 2012, 23:01:42

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132