【发布时间】:2020-01-06 02:13:58
【问题描述】:
使用下面的代码,我尝试使用 List 上的 distinct 方法删除重复元素:
class OrderDetSpecific(var size: Double,
var side: String,
var trade_id: Int,
var price: Double,
var time: String,
var code : String) {
override def toString : String = {
this.code+","+this.time+","+this.trade_id+","+this.price
}
}
val l = List(new OrderDetSpecific(1.0 , "1" , 1 , 1.0 , "10" , "a"),new OrderDetSpecific(1.0 , "1" , 1 , 1.0 , "10" , "a"))
println(l.size)
println(l.distinct.size)
返回:
defined class OrderDetSpecific
l: List[OrderDetSpecific] = List(a,10,1,1.0, a,10,1,1.0)
2
2
但是可以看到重复的元素没有被删除。覆盖toString 方法被用作发现重复项的一部分,并且由于存在重复项,那么列表l 的大小应该是1 而不是2,因为调用l.distinct.size?
更新:
转换为案例类:
case class OrderDetSpecific(var size: Double,
var side: String,
var trade_id: Int,
var price: Double,
var time: String,
var code : String) {
override def toString : String = {
this.code+","+this.time+","+this.trade_id+","+this.price
}
}
val l = List(new OrderDetSpecific(1.0 , "1" , 1 , 1.0 , "10" , "a"),new OrderDetSpecific(1.0 , "1" , 1 , 1.0 , "10" , "a"))
println(l.size)
println(l.distinct.size)
现在重复的元素被删除了。案例类是否在 equals 上使用值相等,从而允许 distinct 按预期运行?
当我覆盖等于时:
class OrderDetSpecific(var size: Double,
var side: String,
var trade_id: Int,
var price: Double,
var time: String,
var code : String) {
override def toString : String = {
this.code+","+this.time+","+this.trade_id+","+this.price
}
override def equals(that: Any): Boolean =
that match {
case that: OrderDetSpecific => {
time == that.time
}
case _ => false
}
}
val l = List(new OrderDetSpecific(1.0 , "1" , 1 , 1.0 , "10" , "a"),new OrderDetSpecific(1.0 , "1" , 1 , 1.0 , "10" , "a"))
println(l.size)
println(l.distinct.size)
不删除不同的元素。由于我的覆盖位于 time 属性上,该属性并不明显,不应该删除重复的元素吗?
【问题讨论】:
-
distinct内部使用equals,对于普通类使用引用相等而不是值相等,因此所有这些元素都是不同的,无论它们具有相同的值(同时考虑到所有这些值都是可变的,它们具有相同的值只是巧合,以后可能会更改)。 - 所以它的行为符合预期。如果您愿意,您可以使所有这些值不可变并改用 case 类,或者您可以自己重写equals(但请记住,对于可变值,引用相等 是唯一“健全”的实现方式). -
在列表中为 vars 的持有者添加
case并不邪恶。但更喜欢不可变和小心使用 Maps 和 Sets。 -
@texasbruce 可能他在谈论“人类可读性”来验证输出。
-
@Luis Miguel Mejía Suárez 谢谢,请查看问题更新。为什么它是“对于可变值,引用相等是唯一的”理智的“实现”?
-
@blue-sky 具有可变值的 案例类 是代码异味。对于你自己的equals,可能你还需要覆盖
canEquals&hashcode,你可以通过谷歌搜索“有效的Java自定义equals”,或者这就是为什么在Scala 我们通常不用担心,直接使用case classes。最后,对于可变值,人们可能会争辩说,只有当它们是完全相同的实例时它们才相等。 值相等对于值可以改变的东西没有意义。
标签: scala duplicates