views:

594

answers:

4

I need a map that has two keys, e.g.

Map2<String /*ssn*/, String /*empId*/, Employee> _employees;

So that I can

_employees.put(e.ssn(), e.empId(), e)

And later

_employees.get1(someSsn);
_employees.get2(someImpId);

Or even

_employees.remove1(someImpId);

I am not sure why I want to stop at two, why not more, probably because that's the case I am I need right now :-) But the type needs to handle fixed number of keys to be type-safe -- type parameters cannot be vararg :-)

Appreciate any pointers, or advice on why this is a bad idea.

+3  A: 

My first thought was: the easiest way to do this, I think, would be two maps.

Map< String, Map< String,Employee> > _employees;

But from what it looks like, you just want to be able to look up an employee by either SSN or ID. What's to stop you then from making two maps, or at worst a class that contains two maps?

As a clarification, are you looking for a compound key being employees are uniquely identified by the combination of their SSN and ID, but not either one by itself, or are you looking for two different ways of referencing an employee?

Stefan Mai
No, it's not a composite key, but two different keys.Two maps is exactly what I am doing right now. Already in two different classes. When I needed it in a third class, I decided to write a Map2 class, but wanted to check first if one already existed.
Hemal Pandya
+3  A: 

I imagine the main key would be empId, so I would build a Map with that as the key, i.e. empId ---> Employee. All other unique attributes (e.g. ssn) would be treated as secondary and will use separate Maps as a lookup table for empId (e.g. ssn ---> empId).

This implementation makes it easy to add/remove employees, since you only need to change one Map, i.e. empId ---> Employee; the other Maps can be rebuilt only when needed.

Zach Scrivena
Interesting. It allows deletion from any key, even if there any many. It might help me solve the problems I face with @krosenvold approach.
Hemal Pandya
A: 

If the empId cannot conflict with a SSN (a big assumption I'm making), then you don't really need two Maps. Just do two inserts for each employee. (Maps store references, not objects, so this won't take a lot more memory.) If the empId does conflict with the SSN format, you can always change the type parameter of the Map Key to Object and create a wrapper class for your keys.

Map<String /*ssn or empId*/, Employee> _employees;
_employees.put(e.ssn(), e);
_employees.put(e.empId(), e);

This just maps two keys to the same employee. Consequently, you should get the same Employee object from the following two method calls.

_employees.get(someSsn);
_employees.get(someImpId);

The best part is, if you need to add more keys later you can. Just make sure they don't conflict with the format of SSN or empId (or wrap them, as I suggested earlier). The worst drawback that I can see to this method is that you'd need to do two remove operations when you want to delete an employee. So, for example, if you want to remove an employee with a certain empId, you'd have to get that employee, then remove them based on all the keys in your Map.

SSNs are always nine decimal digits (in the U.S.). If your employee ID is any other format, then you can use this solution.

Bill the Lizard
Just got gets this sounds interesting. Even if the keys can clash, I could either use a Pair<String, Object> as key to differentiate. But remove and iterator would still be difficult
Hemal Pandya
Remove wouldn't be too bad. I hadn't really thought about an iterator. That would be a problem, since you either get an iterator of the Keys, or of all Entrys (which is Key and Value).
Bill the Lizard
Either way, you'd have duplicate Employees in your iterator. You could get around this by storing Employees separately in a Set, but then you're getting close to implementing your own data structure. I think two Maps is a better solution.
Bill the Lizard
+1  A: 

The Spiffy Framework appears to provide exactly what you`re looking for. From the Javadocs:

A two-dimensional hashmap, is a HashMap that enables you to refer to values via two keys rather than one

The relevant class is TwoDHashMap. It also provides a ThreeDHashMap.

Don
The x-DHashMap seems like a Map with a single but compound x-dimensional key... you can't use each key independently to access the values.
Zach Scrivena