How to represent an uninitialized (aka null) Map in scala - scala

How does one represent null in scala for collections?
The equivalent for List's would be "Nil" and it would be represented as follows:
Nil.asInstanceOf[Map[String,String]]
What is the equivalent for Maps?
UPDATE The two working solutions that I am aware of, from experimenting as well as from the suggested solutions are "Map()" and "null.asInstanceOf(Map[String,String])". The Map() is not what I intended: i did not want an empty item but actually a non-existent one (aka null in java). I was already aware that Nil is only for Lists: it was intended to illustrate the flavor of entity I was searching for used by Map's. Using "null.asInstanceOf(..)" is not a scala-ish idiom. It appears there are no equivalents for Map ..?

The best way do to it is:
val x = Map.empty[String, String]
With a mutable map:
import scala.collection.mutable.{ Map => MMap }
val y = MMap.empty[String, String]

Nil is just an empty List. It is not related to null in any way.
Scala has null, just like Java, but it should almost always be avoided.
What is your actual goal?
Do you want an empty Map?
val m = Map[String,String]()
Or an empty mutable Map that can be added to?
val m = collection.mutable.Map[String,String]()
Or an Option[Map] that can be initialized later?
val m: Option[Map[String,String]] = None
Or actually a null?
var m: Map[String,String] = null

Related

Scala: flatten mixed set of sets (or lists or arrays)

I have a Set which incorporates a combination of strings, and subSets of strings, like so:
val s = Set(brand1-_test, Set(brand-one, brand_one, brandone), brands-two, brandthree1, Set(brand-three2, brand_three2, brandthree2))
How do I flatten this so that I have one flat set of strings? s.flatten doesn't work with the following error:
error: No implicit view available from Object => scala.collection.GenTraversableOnce[B]
Neither does flatMap. What am I missing here? The Set could just as easily incorporate a subLists or subArrays (they are the result of a previous function), if that makes a difference.
s.flatMap { case x:Iterable[_] => x; case y => Seq(y) }
Try putting it in a REPL:
scala> val s = Set("s1", Set("s2", "s3"))
s: scala.collection.immutable.Set[Object] = Set(s1, Set(s2, s3))
since you are providing two types (Set and String) then scala infers a type which covers both (Object in this case, but probably Any or AnyRef in most cases) which is not a collection and therefore cannot be flattened.

Converting a Scala Map to a List

I have a map that I need to map to a different type, and the result needs to be a List. I have two ways (seemingly) to accomplish what I want, since calling map on a map seems to always result in a map. Assuming I have some map that looks like:
val input = Map[String, List[Int]]("rk1" -> List(1,2,3), "rk2" -> List(4,5,6))
I can either do:
val output = input.map{ case(k,v) => (k.getBytes, v) } toList
Or:
val output = input.foldRight(List[Pair[Array[Byte], List[Int]]]()){ (el, res) =>
(el._1.getBytes, el._2) :: res
}
In the first example I convert the type, and then call toList. I assume the runtime is something like O(n*2) and the space required is n*2. In the second example, I convert the type and generate the list in one go. I assume the runtime is O(n) and the space required is n.
My question is, are these essentially identical or does the second conversion cut down on memory/time/etc? Additionally, where can I find information on storage and runtime costs of various scala conversions?
Thanks in advance.
My favorite way to do this kind of things is like this:
input.map { case (k,v) => (k.getBytes, v) }(collection.breakOut): List[(Array[Byte], List[Int])]
With this syntax, you are passing to map the builder it needs to reconstruct the resulting collection. (Actually, not a builder, but a builder factory. Read more about Scala's CanBuildFroms if you are interested.) collection.breakOut can exactly be used when you want to change from one collection type to another while doing a map, flatMap, etc. — the only bad part is that you have to use the full type annotation for it to be effective (here, I used a type ascription after the expression). Then, there's no intermediary collection being built, and the list is constructed while mapping.
Mapping over a view in the first example could cut down on the space requirement for a large map:
val output = input.view.map{ case(k,v) => (k.getBytes, v) } toList

Scala type mismatch problem (expected Map, found scala.collection.mutable.HashMap)

I am still a newbie Scala programmer, so sorry if this question may look naive, but I searched for a while and found no solutions. I am using Scala 2.8, and I have a class PXGivenZ defined as:
class PXGivenZ (val x:Int, val z:Seq[Int], val values: Map[Seq[Int], Map[Int, Double]] ){...}
When I try to instantiate an element of that class into another block of program like this:
// x is an Int
// z is a LinkedList of Int
...
var zMap = new HashMap[Seq[Int], HashMap[Int, Double]]
...
val pxgivenz = new PXGivenZ(x, z, zMap)
I get the following error:
found : scala.collection.mutable.HashMap[Seq[Int],scala.collection.mutable.HashMap[Int,Double]]
required: Map[Seq[Int],Map[Int,Double]]
val pxgivenz = new PXGivenZ(x, z, zMap)
^
There is clearly something I don't get: how is a Map[Seq[Int],Map[Int,Double]] different from a HashMap[Seq[Int], HashMap[Int,Double]]? Or is something wrong with the "mutable" classes?
Thanks in advance to anyone who will help me!
By default, the Map that is imported in a scala file is scala.collection.immutable.Map and not scala.collection.Map. And of course, in your case, HashMap is a mutable map, not an immutable one.
Thus if you want that Map refers to scala.collection.Map in your file, you have to import it explicitely:
import scala.collection.Map
The reason of this choice is that you will not manipulate an immutable and a mutable structure in the same way. Thus, scala infers by default that you will use immutable structure which are "most secure". If you don't want to do so, you must change it explicitly.

Map inside Map in Scala

I've this code :
val total = ListMap[String,HashMap[Int,_]]
val hm1 = new HashMap[Int,String]
val hm2 = new HashMap[Int,Int]
...
//insert values in hm1 and in hm2
...
total += "key1" -> hm1
total += "key2" -> hm2
....
val get = HashMap[Int,String] = total.get("key1") match {
case a : HashMap[Int,String] => a
}
This work, but I would know if exists a better (more readable) way to do this.
Thanks to all !
It looks like you're trying to re-implement tuples as maps.
val total : ( Map[Int,String], Map[Int,Int]) = ...
def get : Map[Int,String] = total._1
(edit: oh, sorry, I get it now)
Here's the thing: the code above doesn't work. Type parameters are erased, so the match above will ALWAYS return true -- try it with key2, for example.
If you want to store multiple types on a Map and retrieve them latter, you'll need to use Manifest and specialized get and put methods. But this has already been answers on Stack Overflow, so I won't repeat myself here.
Your total map, containing maps with non uniform value types, would be best avoided. The question is, when you retrieve the map at "key1", and then cast it to a map of strings, why did you choose String?
The most trivial reason might be that key1 and so on are simply constants, that you know all of them when you write your code. In that case, you probably should have a val for each of your maps, and dispense with map of maps entirely.
It might be that the calls made by the client code have this knowledge. Say that the client does stringMap("key1"), or intMap("key2") or that one way or another, the call implies that some given type is expected. That the client is responsible for not mixing types and names. Again in that case, there is no reason for total. You would have a map of string maps, a map of int maps (provided that you are previous knowledge of a limited number of value types)
What is your reason to have total?
First of all: this is a non-answer (as I would not recommend the approach I discuss), but it was too long for a comment.
If you haven't got too many different keys in your ListMap, I would suggest trying Malvolio's answer.
Otherwise, due to type erasure, the other approaches based on pattern matching are practically equivalent to this (which works, but is very unsafe):
val get = total("key1").asInstanceOf[HashMap[Int, String]]
the reasons why this is unsafe (unless you like living dangerously) are:
total("key1") is not returning an Option (unlike total.get("key1")). If "key1" does not exist, it will throw a NoSuchElementException. I wasn't sure how you were planning to manage the "None" case anyway.
asInstanceOf will also happily cast total("key2") - which should be a HashMap[Int, Int], but is at this point a HashMap[Int, Any] - to a HashMap[Int, String]. You will have problem later on when you try to access the Int value (which now scala believes is a String)

How to access value of map with a key if key was not found in scala?

Assume I have
var mp = Map[String,String]()
.....
val n = mp("kk")
The above will throw runtime error in case key "kk" did not exist.
I expected n will be null in case key did not exist. I want n to be null if key did not exist.
What is the proper way to handle this situation in scala with a short code sample?
First of all, you probably don't really want null, as that's almost always a sign of bad coding in Scala. What you want is for n to be of type Option[String], which says that the value is either a String or is missing. The right way to do that is with the .get() method on you map
val n = mp.get("kk")
If you really do need null (for interop with Java libraries, for example), you can use .getOrElse()
val n = mp.getOrElse("kk", null)
Try this:
val valueOpt = mp.get("kk")
Your result is of type Option[String] and can be either None or Some(actualValue). You can use pattern matching to find out:
valueOpt match {
case Some(value) => println(value)
case None => println("default")
}
A more appropriate way to do that kind of things, however, is to use the methods on Option, e.g.:
println(valueOpt.getOrElse("default"))
Look for the API docs for Option there.
Edit: Note that Mapitself directly defines a getOrElse method, too, as shown in Dave's answer.
val conversionRatios:mutable.Map[String, Double] = mutable.Map[String, Double](
"USD" -> 2.0,
"CNY" -> 3.0
)
val currentRate = conversionRatios.apply(key) // it will return you value or NoSuchElementException will be thrown