0

I want to maintain a Map of case class objects, such that I can add new instances and look them up by an ID.

My current (very ugly) solution (stripped down):

case class cc(i: Int)

var myccmap: Map[Int, cc] = null

def addcc(thecc: cc): cc = {
    if (myccmap == null) {
        myccmap = Map(thecc.hashCode, thecc)
    }
    else {
        myccmap = myccmap ++ Map(thecc.hashCode, thecc)
    }
    thecc
}

And then elsewhere I can use val somecc = addcc(cc(56)), for example, to maintain a Map of my cc objects added with addcc.

This way, I can store the key, which is just the hashCode, with some data in a file, and then when I read the file, I can extract the cc object by looking up the hashCode (which may or may not be present in myccmap).

Is there a better way to do this, ideally without relying on a check for null?

Alfredo Gimenez
  • 2,174
  • 1
  • 14
  • 19
  • Ok, I just discovered I can use `Map()` to create an empty map. That eliminates the check for `null`. Keeping it up in case someone has a better solution... – Alfredo Gimenez Jun 23 '16 at 23:41
  • you should probably use `Map.empty` to create the empty Map – Fabian Schmitthenner Jun 24 '16 at 00:27
  • 2
    It's a bad idea for other reasons: 1) because different objects can have the same hashcode, so if you just happen to have two objects like this, you'll end up with really weird errors; 2) hashcodes aren't guaranteed to be stable between program runs. – Alexey Romanov Jun 24 '16 at 06:36
  • @AlexeyRomanov I was aware of the first issue, but I thought the same case class object would have the same hashCode across runs, from reading here http://stackoverflow.com/questions/4526706/what-code-is-generated-for-an-equals-hashcode-method-of-a-case-class . – Alfredo Gimenez Jun 24 '16 at 17:58
  • Only if its parameters have the same hashCode as well. Just run e.g. `object A; println(Some(A)).hashCode)` a couple of times. – Alexey Romanov Jun 25 '16 at 02:46

2 Answers2

2

Your code can be simplified, just use a HashSet if you want to use the hash anyway:

import collection.immutable.HashSet

case class Cc(i: Int)

var myccmap: HashSet[Cc] = HashSet.empty

def addcc(thecc: Cc): thecc.type = {
  myccmap += thecc
  thecc
}    

Also, by convention, classes should start with an uppercase letter. I also used a singleton-type as return value of addcc, this way it's clear that this function really just returns its parameter

Fabian Schmitthenner
  • 1,696
  • 10
  • 22
1

Depends on whether you really want that key or not. I suppose the key of hashcode is still required because you store the key somewhere. And be noticed, don't use var in most of the cases, instead, use mutable map will help.

case class cc(i: Int)

val myccmap: mutable.Map[Int, cc] = mutable.Map.empty

def addcc(thecc: cc): cc = {
    myccmap += (thecc.hashCode -> thecc)
    thecc
}
LynxZh
  • 825
  • 5
  • 9