2013-02-05 43 views
3

我有元素的Set已在平等圍繞一個鍵定義,但其他領域可以是不同的。所以,當我需要「更新」,這是我已經試過:如何「更新」一個不可變的Scala中的不可變元素?

object sandbox { 

    case class K(val id: Int, val message: String) { 
    override def equals(that: Any) = that match { 
     case K(this.id, _) => true 
     case _ => false 
    } 
    override def hashCode = this.id 
    override def toString = "(" + id + "," + message + ")" 
    } 

    val s = Set(K(1, "a"), K(2, "b"))    //> s : scala.collection.immutable.Set[test.sandbox.K] = Set((1,a), (2,b)) 
    val updatedElem = K(1, "c")      //> updatedElem : test.sandbox.K = (1,c) 

    s + updatedElem         //> res0: scala.collection.immutable.Set[test.sandbox.K] = Set((1,a), (2,b)) 

    Set(updatedElem) | s       //> res1: scala.collection.immutable.Set[test.sandbox.K] = Set((1,c), (2,b)) 
    } 

添加已經存在的元素不會改變集合,並且先刪除它並再次添加更新似乎是次優。

union方法在左側保留了該組的元素,但該行爲沒有記錄;所以我不應該依賴它。

那麼現在有什麼更明顯的我失蹤了嗎?我應該依賴實際行爲(並且爲了防止它發生變化而編寫測試)?還是應該分兩步進行更新?

+0

該集合正在使用僅依賴於'id'的哈希碼。這意味着'K(1,「a」)== K(1,「c」)'並且會解釋set不會添加(沒有拋出異常)。嘗試使用不同消息的哈希值。 – korefn

+0

那麼我會得到兩個對象,而不是前一個替換 – fortran

回答

5

從我的角度來看,它實際上是一個建模中的概念問題。關鍵是相同的對象應該是等價的,否則你可能會考慮其他一些結構。例如,爲什麼不嘗試Map,將id映射到message(或idK(id,message))?這在概念上似乎更清晰,然後您可以使用.updated(1,"c")來更新它。

+0

是的,這是我正在考慮的另一種選擇;但大多數時候我認爲我需要訪問包括密鑰在內的整個結構(還有一些字段更多),所以我認爲該集合會更方便。 – fortran

+0

@fortran你能展示一個你構建的集合的用例嗎?我認爲你很清楚如何創建和修改該設置,但我看不到你是如何使用它的。如果你可以在問題中提供這些信息,也許人們可以提供更多幫助。 – Kane

+0

我還沒有一個,這只是一種感覺^ _ ^這是一個遊戲,它是持有當前得分,手中的代幣等的「玩家」結構。 – fortran

相關問題