0

If I have a java.util.Map[String,Java.util.Map] for the first call, correct overloaded method is called: toScala(java.util.Map[_,_]). But in the mapValues invocation, function toScala(other:Any) is called. How to avoid this? I would be calling toScala using a java object like Map, List, Int, String. The map may contain another java.util.Map/java.util.List/ String/Int as one of its values. Similarly the list may also contain another java.util.List/ String/ Int as its members

  private def toScala(map:java.util.Map[_,_]) : Any = { 
    map match {
      case null => Map.empty
      case _ => map.asScala.mapValues(toScala).toMap
    }
  }

  private def toScala(list:java.util.List[_]) : Any = {
    list match {
      case null => List.empty
      case _ =>  list.asScala.map(toScala).toList
    }
  }

  private def toScala(other:Any) : Any =  {
    other match {
      case null => None
      case _ => other
    }
  }
bugs
  • 1
  • 2
  • Use proper types instead of wildcards and `Any`. I am not sure what exacly you want to do but typeclasses might be the solution. – Łukasz Mar 23 '16 at 09:37
  • But i cannot do that as my Map might contain values of types List,String,Int,Map etc. I am trying to build a ScalaAppconfigWrapper over JavaAppConfigWrapper – bugs Mar 23 '16 at 09:42
  • Please edit your question to show us how you are calling the code . What you expect to solve clearly. – Som Bhattacharyya Mar 23 '16 at 10:11

1 Answers1

0

Maybe this helps you:

private def toScala(v: Any): Any = vmatch {
  case null => throw new NullPointerException("null value encountered while converting Java to Scala")
  case m: java.util.Map[_, _] => m.asScala.mapValues(toScala).toMap
  case m: java.util.List[_] => m.asScala.map(toScala).toMap
  case m: java.util.Set[_] => m.asScala.map(toScala).toMap
  case m => m
}

Or:

private def toScalaOption(v: Any): Any = vmatch {
  case null => None
  case m: java.util.Map[_, _] => m.asScala.mapValues(toScala).toMap
  case m: java.util.List[_] => m.asScala.map(toScala).toMap
  case m: java.util.Set[_] => m.asScala.map(toScala).toMap
  case m => Some(m)
}

Cheers

Joan
  • 4,079
  • 2
  • 28
  • 37
  • I am doing something like this right now Joan but i would like to use overloading is it possible. – bugs Mar 23 '16 at 10:56
  • 1
    Not possible: overloading is resolved entirely at compile time based on the static types of the arguments, so if the map values are of type `Any`, you'll have to discriminate the possible value types at runtime (as Joan is doing here). – Régis Jean-Gilles Mar 23 '16 at 16:42