2

I have a java map, stringMap, where the keys are strings that represent dates and the values are longs. I need to convert this map into a collection.mutable.HashMap[DateTime, Long] That is, in addition to changing the type of map, I need to change from Strings to DateTimes.

This is the solution I am currently using:

import scala.collection.JavaConversions._
val df = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
val stringMap: java.util.HashMap[String, Long] = ...
val dateTimeMap = stringMap map { case (k, v) => (df.parseDateTime(k), v)}
val result = collection.mutable.HashMap[DateTime, Long](dateTimeMap.toArray:_*)

The last line comes from this post

Note there is an implicit conversion converting stringMap to a scala Hashmap.

The question is this, is there a better way to do this? I tried using a for yield / the map method with breakout, but they were returning a Map instead of a collection.mutable.HashMap EDIT: Apparently breakout does work. /EDIT

Preferably there would be a functional programming way to do this without the need for a temporary dateTimeMap

Community
  • 1
  • 1
Kevin Wheeler
  • 1,331
  • 2
  • 15
  • 24

2 Answers2

3

First, it's advisable to use JavaConverters instead to get an explicit conversion to avoid accidentally converting multiple times.

You should be able to use breakOut on map by specifying the expected result type:

import scala.collection.breakOut
import scala.collection.JavaConverters._

val stringMap: java.util.HashMap[String, Long] = new java.util.HashMap()
stringMap.put("1", 1L)
stringMap.put("2", 2L)

val result: collection.mutable.HashMap[Int, Long] = stringMap.asScala.map { case (k, v) => (k.toInt, v) }(breakOut)
// result: scala.collection.mutable.HashMap[Int,Long] = Map(2 -> 2, 1 -> 1)
dhg
  • 52,383
  • 8
  • 123
  • 144
  • So it turns out if you do this exact same thing, except try to use an implicit conversion instead of asScala, it doesn't work. Unfortunately the style convention for the project I'm working on is to use implicit conversions rather than use any explicit conversions. Is there a way to make this work while adhering to their style conventions? – Kevin Wheeler Dec 18 '14 at 02:15
  • The implicit version works for me. Just replace `JavaConverters` with `JavaConversions` and drop the `.asScala` and it should work. – dhg Dec 18 '14 at 03:24
  • Oh, you're right. I tried replacing the dot before `map` with a space. Thanks. – Kevin Wheeler Dec 18 '14 at 05:16
0

If I understand your question if this should work.

  val result = collection.mutable.HashMap[DateTime, Long](stringMap.map{ case (k,v) => (df.parseDateTime(k),v)}.toArray:_* )
Soumya Simanta
  • 11,523
  • 24
  • 106
  • 161
  • This solution basically just makes the dateTimeMap without ever giving it a name. I was hoping to not have to make this temporary map, just to throw it away a second later. I was hoping to skip making this temporary map and go straight to creating the result map. – Kevin Wheeler Dec 18 '14 at 01:45
  • @KevinWheeler - oh okay. I guess dhg solution above should work then? – Soumya Simanta Dec 18 '14 at 01:53