Статьи

Индивидуальный заказ Scala TreeMap

Как вы получаете индивидуальный заказ в Scala TreeMap ?

Ну, это озадачило меня на некоторое время. Ответ лежит в мире импликатов и преобразователей типов приемников.

В скорлупе орехов scala.collection.immutable.TreeMap является SortedMap . Если вы посмотрите на документацию по TreeMap , вы увидите, что в качестве неявного аргумента принимается Ordering[T] .

Обычно, когда вы объявляете TreeMap , скажем, встроенный, он будет использовать объект Ordering по умолчанию, например, так:

1
2
scala> val dtm = TreeMap( "a" -> 1, "bc" -> 2, "def" -> 3 )
dtm: scala.collection.immutable.TreeMap1 = Map(a -> 1, bc -> 2, def -> 3)

Если вы хотите изменить порядок ключей, например, вместо возрастающего порядка по содержимому String, скажем, в порядке убывания длины строк, вам нужен тип Ordering.

1
2
3
4
scala> object VarNameOrdering extends Ordering[String] {
         def compare(a:String, b:String) = b.length compare a.length
       }
defined module VarNameOrdering

Теперь вы можете использовать второй список аргументов в явном виде, например так:

1
2
scala> val tm1 = TreeMap( "a" -> 1, "bc" -> 2, "def" -> 3 )( VarNameOrdering )
tm: scala.collection.immutable.TreeMap1 = Map(def -> 3, bc -> 2, a -> 1)

Мы передаем объект в TreeMap , который довольно похож на объект Java Collection Comparator без создания шаблона. Ключи TreeMap теперь упорядочены по длинам строк. Мы добавим больше элементов, и карта останется упорядоченной.

1
2
val tm2 = tm1 + ( "food" -> 4 )
cala.collection.immutable.TreeMap1 = Map(food -> 4, def -> 3, bc -> 2, a -> 1)

Однако, предостережение, нужно быть осторожным и помнить, что карты обычно реализуются в виде хэшей.

1
2
scala> val tm3 = tm2 + ( "z" -> 5 )
tm3: scala.collection.immutable.TreeMap1 = Map(food -> 4, def -> 3, bc -> 2, z -> 5)

Удивлены? Вы должны быть.

Другой способ сортировки карты — просто получить доступ к ключам и выполнить сортировку.

1
2
3
4
5
6
7
8
scala> dtm.keys.toList.sortWith ( _.length > _.length )
res3: List1 = List(salad, def, bc, a)
 
scala> dtm.keys.toList.sortWith ( _.length > _.length ).map( k => ( dtm.get(k).get ))
res4: List[Int] = List(10, 3, 2, 1)
 
scala> dtm.keys.toList.sortWith ( _.length > _.length ).map( k => ( k, dtm.get(k).get ))
res5: List[(java.lang.String, Int)] = List((salad,10), (def,3), (bc,2), (a,1))

Это может быть лучшим решением, так как вы не потеряли ключ в полете! Рассмотрение того, как будут храниться данные, является важным решением, которое необходимо принять на ранней стадии. Вы всегда можете решить, как написать проекцию этих данных намного позже.

Наконец, интересно увидеть параллели между Java и Scala

1
2
3
4
5
scala> dtm.keys
res6: Iterable1 = Set(a, bc, def, salad)
 
scala> dtm.keys.toList
res7: List1 = List(a, bc, def, salad)

Ссылка: Индивидуальный заказ Scala TreeMap от нашего партнера JCG Питера Пилигрима в блоге Питера Пилигрима .