Возможность состоит в том, чтобы создать свой собственный Set
элемент, заключая в себе 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 не позволяет вам получить Item("a", 50)
в результате.Если вы хотите сделать это, я предлагаю Map[String, Item]
вместо Set[Item]
для items
(и, конечно, соответственно изменить код).
РЕДАКТИРОВАТЬ: Дляболее любопытно, вот быстро написанная версия предмета, который я использую:
case class Item(id: String, score: Int) {
override def equals(y: Any) =
y != null && {
PartialFunction.cond(y) {
case Item(`id`, _) => true
}
}
}