Scala:如何让自定义排序的SortedSet保留排序值相同的不同对象?
问题原因与解决方案
这个问题的核心在于Scala的SortedSet是通过你提供的Ordering来判断元素是否相等的,而不是依赖Edge类的equals方法。
当你定义的edgeCostOrdering只根据计算出的优先级值进行比较时,只要两个Edge的优先级值相同,Ordering.compare(a, b)就会返回0。在SortedSet的规则里,这意味着a和b是同一个元素,所以后续添加的元素会覆盖之前的——哪怕它们的firstId、secondId完全不同。
解决方法:扩展排序规则,区分相同优先级的不同Edge
你需要修改Ordering,让它在优先级值相同时,进一步比较Edge本身的属性,确保不同的Edge对象即使优先级相同也能被识别为不同元素。比如可以把优先级和Edge的所有属性组合成一个元组,利用Scala元组默认的顺序比较逻辑:
object Ord { val edgeCostOrdering: Ordering[Edge] = Ordering.by { edge: Edge => val priority = if (edge.secondId == goalId) graphRepresentation.calculateStraightLineCost(edge.firstId, goalId) else edge.cost + graphRepresentation.calculateStraightLineCost(edge.secondId, goalId) // 先按优先级排序,优先级相同则依次比较firstId、secondId、cost (priority, edge.firstId, edge.secondId, edge.cost) } }
这样修改后,当两个Edge的优先级相同时,SortedSet会继续比较它们的firstId;如果firstId也相同,再比较secondId;最后比较cost。只有当所有属性都完全相同时,才会被视为同一个元素,否则都会被保留在集合里。
额外说明
如果你不关心相同优先级元素的具体排序顺序,只需要确保它们能共存,也可以在优先级之后加上edge.hashCode(),但直接比较具体属性更可靠(因为哈希值存在碰撞的可能性)。
内容的提问来源于stack exchange,提问作者UtheMan
相关产品推荐
相关产品推荐

