{"id":668,"date":"2012-07-12T12:49:17","date_gmt":"2012-07-12T11:49:17","guid":{"rendered":"http:\/\/www.xenonique.co.uk\/blog\/?p=668"},"modified":"2012-07-12T12:49:17","modified_gmt":"2012-07-12T11:49:17","slug":"custom-ordering-scala-treemap","status":"publish","type":"post","link":"https:\/\/www.xenonique.co.uk\/blog\/2012\/07\/12\/custom-ordering-scala-treemap\/","title":{"rendered":"Custom Ordering Scala TreeMap"},"content":{"rendered":"<p>How do you get custom ordering in a Scala <a href=\"https:\/\/www.scala-lang.org\/api\/current\/index.html#scala.collection.immutable.TreeMaphttps:\/\/\" title=\"TreeMap Scala Docs API\"><code>TreeMap<\/code><\/a>?<\/p>\n<p>Well this puzzled me for a while. The answer lies in the world of implicits and receiver type converters. <\/p>\n<p>In a nut shell, a <code>scala.collection.immutable.TreeMap<\/code> is a <a href=\"https:\/\/www.scala-lang.org\/api\/current\/index.html#scala.collection.immutable.SortedMap\" title=\"SortedMap API\"><code>SortedMap<\/code><\/a>. If you look at the documentation for <code>TreeMap<\/code>, you will see it takes an <a href=\"https:\/\/www.scala-lang.org\/api\/current\/index.html#scala.math.Ordering\" title=\"Ordering Scala Doc API\"><code>Ordering[T]<\/code><\/a> as an implicit argument.<\/p>\n<p>Normally when you declare a <code>TreeMap<\/code>, say inline, it will use the default <code>Ordering <\/code>object like so:-<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nscala&gt; val dtm = TreeMap( &quot;a&quot; -&gt; 1, &quot;bc&quot; -&gt; 2, &quot;def&quot; -&gt; 3 )\r\ndtm: scala.collection.immutable.TreeMap[java.lang.String,Int] = Map(a -&gt; 1, bc -&gt; 2, def -&gt; 3)\r\n<\/pre>\n<p>If you want to change the ordering of the keys, for example, instead of the ascending order by String content, into, say, a descending order of strings length then you need an Ordering type.<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nscala&gt; object VarNameOrdering extends Ordering[String] {\r\n         def compare(a:String, b:String) = b.length compare a.length\r\n       }\r\ndefined module VarNameOrdering\r\n<\/pre>\n<p>Now you can use the second argument list in an explicit fashion like this:<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nscala&gt; val tm1 = TreeMap( &quot;a&quot; -&gt; 1, &quot;bc&quot; -&gt; 2, &quot;def&quot; -&gt; 3 )( VarNameOrdering )\r\ntm: scala.collection.immutable.TreeMap[java.lang.String,Int] = Map(def -&gt; 3, bc -&gt; 2, a -&gt; 1)\r\n<\/pre>\n<p>We pass the object to the <code>TreeMap<\/code>, which is rather similiar to a Java Collection <code>Comparator <\/code>object without the boilerplate instantiation. The keys of the TreeMap are now ordered by String lengths. We add more elements and the map will stay ordered.<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\n val tm2 = tm1 + ( &quot;food&quot; -&gt; 4 )\r\ncala.collection.immutable.TreeMap[java.lang.String,Int] = Map(food -&gt; 4, def -&gt; 3, bc -&gt; 2, a -&gt; 1)\r\n<\/pre>\n<p>However, a word of caution, one needs to be careful and remember that maps are usually implemented as hashes.<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nscala&gt; val tm3 = tm2 + ( &quot;z&quot; -&gt; 5 )\r\ntm3: scala.collection.immutable.TreeMap[java.lang.String,Int] = Map(food -&gt; 4, def -&gt; 3, bc -&gt; 2, z -&gt; 5)\r\n<\/pre>\n<p>Surprised? You should be.<\/p>\n<p>Another way to sort a map is just to get access to the keys and sort.<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nscala&gt; dtm.keys.toList.sortWith ( _.length &gt; _.length )\r\nres3: List[java.lang.String] = List(salad, def, bc, a)\r\n\r\nscala&gt; dtm.keys.toList.sortWith ( _.length &gt; _.length ).map( k =&gt; ( dtm.get(k).get ))\r\nres4: List[Int] = List(10, 3, 2, 1)\r\n\r\nscala&gt; dtm.keys.toList.sortWith ( _.length &gt; _.length ).map( k =&gt; ( k, dtm.get(k).get ))\r\nres5: List[(java.lang.String, Int)] = List((salad,10), (def,3), (bc,2), (a,1))\r\n<\/pre>\n<p>This may well be a better solution, as you have not lost a key in flight! Considering how data is going to be stored is a major decision that needs to be taken early. You can always decide how to write projection of that data much later.<\/p>\n<p>Finally, it is interesting to see the parallels between Java and Scala<\/p>\n<pre class=\"brush: scala; title: ; notranslate\" title=\"\">\r\nscala&gt; dtm.keys\r\nres6: Iterable[java.lang.String] = Set(a, bc, def, salad)\r\n\r\nscala&gt; dtm.keys.toList\r\nres7: List[java.lang.String] = List(a, bc, def, salad)\r\n<\/pre>\n<p>PS: I can safely say I have used Scala professionally today in financial enterprise.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How do you get custom ordering in a Scala TreeMap? Well this puzzled me for a while. The answer lies in the world of implicits and receiver type converters. In a nut shell, a scala.collection.immutable.TreeMap is a SortedMap. If you look at the documentation for TreeMap, you will see it takes an Ordering[T] as an [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[75,44,40,6],"tags":[],"_links":{"self":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts\/668"}],"collection":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=668"}],"version-history":[{"count":5,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts\/668\/revisions"}],"predecessor-version":[{"id":673,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts\/668\/revisions\/673"}],"wp:attachment":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}