用于自定义的Scala或java数据结构;“不严格”;分类

用于自定义的Scala或java数据结构;“不严格”;分类,java,scala,sorting,data-structures,Java,Scala,Sorting,Data Structures,我有一组具有不同等式和排序语义的项。例如 class Item( val uid: String, // equality val score: Int // sorting ) 我需要的是让一些集合中的项目一直按分数排序。 额外的好处是通过相等性进行快速查找/成员资格检查(如在哈希/树中) 相等的项可以有不同的分数,因此我不能用分数相等作为相等的前缀(即使用一种树/哈希映射) 关于组合scala或java std集合以实现这一点(使用最少的编码)有什么想法吗?:) 我可能会使用

我有一组具有不同等式和排序语义的项。例如

class Item( 
  val uid: String, // equality
  val score: Int   // sorting
)
我需要的是让一些集合中的项目一直按分数排序。 额外的好处是通过相等性进行快速查找/成员资格检查(如在哈希/树中)

相等的项可以有不同的分数,因此我不能用分数相等作为相等的前缀(即使用一种树/哈希映射)

关于组合scala或java std集合以实现这一点(使用最少的编码)有什么想法吗?:)

我可能会使用,因为它们已经排序了。正如Woot4Moo所指出的,您可以创建自己的可比较的(尽管我建议使用Scala)。如果您将该排序作为参数传递给SortedSet,则该集合将为您排序所有内容-SortedSet始终已排序

注意:这是您需要的隐式参数,因此它可能看起来像这样:

val ordering = Ordering[...]
val set = SortedSet(1, 2, 3, ... n)(ordering)

注:最后一个参数是作为排序给出的。一种可能性是构建您自己的
项目集
,包括
SortedMap[Int,Set[item]]
(用于排序)和
HashSet[item]
(用于访问性能:

class MyOrderedSet(items: Set[Item], byPrice: collection.SortedMap[Int, Set[Item]]) extends Set[Item] {

  def contains(key: Item) = items contains key

  def iterator = byPrice map {_._2.iterator} reduceOption {_ ++ _} getOrElse Iterator.empty

  def +(elem: Item) =
    new MyOrderedSet(items + elem, byPrice + (elem.score -> (byPrice.getOrElse(elem.score, Set.empty) + elem)))

  def -(elem: Item) =
    new MyOrderedSet(items - elem, byPrice + (elem.score -> (byPrice.getOrElse(elem.score, Set.empty) - elem)))

  // override any other methods for your convenience
}

object MyOrderedSet {
  def empty = new MyOrderedSet(Set.empty, collection.SortedMap.empty)

  // add any other factory method
}
修改集合是痛苦的,因为您同步了2个集合,但您想要的所有功能都在那里(至少我希望如此)

一个简单的例子:

scala> MyOrderedSet.empty + Item("a", 50) + Item("b", 20) + Item("c", 100)
res44: MyOrderedSet = Set(Item(b,20), Item(a,50), Item(c,100))
还有一个小缺点,实际上与建议的结构无关:您可以检查项目是否在集合中,但无法获取其值:

scala> res44 contains Item("a", 100)
res45: Boolean = true
API中没有任何内容允许您获取
项(“a”,50)
。如果您想这样做,我建议
映射[String,Item]
,而不是
项设置[Item]
(当然,也要相应地更改代码)

编辑:对于更多好奇的人,这里是我使用的物品的快速书写版本:

case class Item(id: String, score: Int) {
  override def equals(y: Any) =
    y != null && {
      PartialFunction.cond(y) {
        case Item(`id`, _) => true
      }
    }
}

+1至少在这个解决方案中,您不需要调整
equals
。这里也有同样的问题。scala中的SortedSet default impl是一个树集,它使用相等顺序…这就是为什么我问:)我不太确定您问的是什么。您是否正在寻找集合的另一个实现或多重哈希问题的特定解决方案?最后,我希望有一个通过键(通过标识)快速查找的自定义集合排序视图。我只是想收集一些关于这件事的想法。考虑到您已经进行了自定义排序,您可能会对本页感兴趣:集合集合案例的性能特征显然支持HashSet。集合的好处是它们总是被排序的,所以需要进行大量的查找,这使得排序很有价值。只要已经定义了排序,Scala库就会真正处理剩下的部分:-)我最终得到的结果是:SortedSet for sorted representation+Map(id->item)for membership/equality。因此,我可以首先找出“集合”中哪些元素是新的/存在的,然后将新元素添加到映射和集合中。通过这种方式,我对视图和严格相等进行了排序。但是,它看起来不太好:(我不能使用just Set作为成员身份,因为没有办法从集合中获取实体,我只能使用contains()true或false。您如何处理添加已在集合中但分数不同的项目的情况?这取决于某种策略(首次获胜、平均值等)但我可以检测和处理。这就是我所说的“不同的相等和排序语义”。并非所有的对象数据都可以形成质量关系,一些临时数据可以在UI中用于表示。我想包装一个
SortedMap[Int,Set[Item]]
太重了吧?