2

I have a

val timestampOffsetMap: Map[ZonedDateTime, Int]

would like to search nearest before timeStamp( a.k.a ZonedDateTime) to getOffset

def getNearestBeforeTimeStampOffset(timeToCheck: ZonedDateTime): Int = ???

I know about sortedMap and thinking about using it, but not sure if there is a better way to solve the problem. Also I am on scala 2.11 for collections API

abroy
  • 83
  • 5
  • Can u post an example input and what should be the output, would help me to implement and test my code – zenwraight Mar 15 '18 at 20:46
  • Sure, Example: Input: ZonedDateTime.now() Output: 28 Usage: `val offset = getNearestBeforeTimeStampOffset(ZonedDateTime.now)` – abroy Mar 15 '18 at 21:08

1 Answers1

2

Update

As Joe Pallas has pointed out, scala's default implementation of TreeMap provides essentially the same functionality as Java's NavigableMap. However, the API is quite different: on TreeMap, there are methods from, to and range, that create ranged projections of the TreeMap. On these ranged projections, the methods headOption and tailOption can be used to select elements that essentially correspond to ceil and floor-elements of a given key.

The reason why the API looks quite different (it returns entire trees instead of a single ceil/floor-elements), is that, somewhat counter-intuitively, building a ranged projection of an immutable tree is asymptotically just as expensive as retrieving a single element.

Nevertheless, I think that there is nothing wrong with using a Java collection for such a specific task, especially if the API is more intuitive. I also suspect that Java's implementation might actually be a tiny bit faster and produce less garbage (that's a speculation, I didn't measure it).


Original answer

Java standard collections provide implementations of NavigableMap, with java.util.TreeMap being one example. The NavigableMap provides methods like floorKey, floorEntry, ceilingKey and ceilingEntry, which seem to do exactly what you want:

import java.util.TreeMap
import java.time.ZonedDateTime

val tm = new TreeMap[ZonedDateTime, Int] // + add entries

def getNearestBeforeTimeStampOffset(timeToCheck: ZonedDateTime)
: Int = tm.floorEntry(timeToCheck).getValue

I'm not sure whether Scala's TreeMap provides a similar functionality, at least it's not called anything with "ceiling" or "floor" in the name. This eternally old question here also didn't point immediately to the functionality analogous to NavigableMap, so maybe it's easier to just use Java's TreeMap in this case.


To convert scala Map to java.util.TreeMap, something like this should work:

val yourMap: Map[ZonedDateTime, Int] = ???

import scala.collection.JavaConverters._
val tm = new java.util.TreeMap((yourMap.asJava : java.util.Map[ZonedDateTime, Int]))
Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • is there an easy way to go from scala Map to Java TreeMap? – abroy Mar 15 '18 at 21:40
  • @abroy added note on conversion. It definitely should work with `JavaConverters` and maybe some type ascription here and there... – Andrey Tyukin Mar 15 '18 at 21:51
  • The ceiling/floor functionality for `TreeMap` is provided by `from` and `to/until` along with `headOption/lastOption`. – Joe Pallas Mar 17 '18 at 21:17
  • @JoePallas You are right. This whole `to/until`-story seems somehow eerily familiar. Indeed, I've even got a [bounty three years ago](https://stackoverflow.com/a/29731450/2707792) for an answer where I was saying exactly that: `TreeMap` provides `to` that corresponds to `floorKey` and `until` that roughly corresponds to `ceilingKey`. Do you want to post it as a separate answer, or should I update my answer? That probably shouldn't be left as just a comment... – Andrey Tyukin Mar 18 '18 at 14:33
  • @AndreyTyukin I'd suggest updating your answer. It's already accepted, so the information may be easier to find the next time someone is looking for it. – Joe Pallas Mar 19 '18 at 15:57