2017-04-17 14 views
0

Kotlinには、データクラスのがあります。データクラスはequals()またはhashCode()を上書きしません。私はセット内に重複したオブジェクトを含むバグに遭遇しており、foo.containsAll(foo)を呼び出すと、そのセットに対してfalseが返されることに気付きました。セット内の重複アイテム

私はセット内の各項目に行きましたが、falsefoo.contains(foo.toList()[i])です。それらの場合、foo.toList()[i] == foo.toList()[i]を呼び出してtrueを返します。したがって、平等チェックが機能します。

ここでは何が起こっていますか?

+1

これを再現するために苦労している:http://ideone.com/n8ydzW。あなたは[最小限のテストケース](http://stackoverflow.com/help/mcve)を構築できますか? –

+0

私は1つを思いつくために唖然としています。しかし、私は回避策を見つけました。 'foo.all {a - > foo.any {b - > a == b}}'は 'containsAll()'の代用として働いています。 –

答えて

2

データクラスに変更可能なものとセットに追加された後のインスタンスの変更状態が含まれている場合、これが可能な唯一の方法(リフレクションの欠如など)があると思います。

data class Foo(var int: Int = 0) 
data class Bar(val string: String, val foo: Foo = Foo()) 

val bars = mutableSetOf<Bar>() 
bars += Bar("") 
bars += Bar("") 

println(bars.containsAll(bars)) // true 

bars.first().foo.int = 12 

println(bars.containsAll(bars)) // false 

これはhashCode()の結果はそれを識別するためにセットで使用されているためですが、あなたのデータクラスのインスタンスの状態変化が、それはおそらく、このような問題を引き起こして異なるハッシュ値を持つことになります。

一般に、この問題を回避するには、マップ内のセットとキーの要素が不変である必要があります。

+0

ありがとう!これが私の問題です。しかし、 'foo.containsAll(foo)'がfalseを返すのはまだ不思議です。 –

+0

はい、単純にハッシュがどのように動作するのか、ハッシュで可変オブジェクトを使用しないでください(マップ内の可変値はキーではなくても問題ありません)。 – mfulton26

関連する問題