2017-04-17 96 views
0

在Kotlin中,我有一個數據類的MutableSet。數據類不會覆蓋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

我正在努力想出一個。但是,我找到了解決方法。使用'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