Reputation: 1820
I want to create a map that has two key :
map.put (key1,key2,value1);// Insert into map
map.get(key1,key2); // return value1
i have looking into multikeyMap but i don't know how i will do it
Upvotes: 9
Views: 5394
Reputation: 92056
It's unfortunate that Java does not support tuples at language level, and therefore you have to go for ad hoc structures like the ones showed in some answers here. This leads to atrocious amount of boilerplate and code duplication.
Functional Java has a library support for tuples. The class that fits the bill here is P2
. The name means "product with 2 elements". (Product is just an algebraic term for composite types.) The library supports tuples of up to 8 elements. The P{n}
classes override all the necessary methods
There is a class named P
that provides a static factory method p
for constructing tuples.
Usage:
import fj.P2;
import fj.Ord;
import fj.data.TreeMap;
import static fj.Ord.*;
import static fj.P.*;
TreeMap<P2<Integer, String>, String> m =
TreeMap.<P2<Integer, String>, String>empty(p2Ord(intOrd, stringOrd)).
set(p(1, "2"), "onetwo").
set(p(5, "3"), "fivethree");
Upvotes: 1
Reputation: 29912
If you always want to access via key1 and key2 together you could just concatenate them with a separator together as key and use a normal map.
Upvotes: 1
Reputation: 198103
If you can use outside libraries, Guava provides exactly this as Table<R, C, V>
, referring to the two keys as "row" and "column" respectively. (Disclosure: I contribute to Guava.)
Upvotes: 2
Reputation: 55223
You might consider using one of Guava's Table
implementations. From the documentation:
A collection that associates an ordered pair of keys, called a row key and a column key, with a single value. A table may be sparse, with only a small fraction of row key / column key pairs possessing a corresponding value.
Upvotes: 2
Reputation: 240898
How about
class Key{
private final String key1;
private final String key2;
//accessors + hashcode + equals()
}
and
Map<Key, Value> map
Upvotes: 10
Reputation: 1500725
Sounds like you just want a key which is created from two values. You may well find that those two values should naturally be encapsulated into another type anyway - or you could create a Key2<K1, K2>
type. (The naming here would allow for Key3
, Key4
etc. I wouldn't encourage you to go too far though.)
For something in between, you could create a private static class within the class where this is really needed (if it's only an internal implementation detail). If it's not a natural encapsulation (e.g. it's something like "name and population", which doesn't make sense outside this specific scenario) then it would be good in terms of keeping meaningful property names, but without exposing it publicly.
In any of these scenarios, you'll end up with a new type with two final variables which are initialized in the constructor, and which contribute to both equals
and hashCode
. For example:
public final class Key2<K1, K2> {
private final K1 part1;
private final K2 part2;
public Key2(K1 part1, K2 part2) {
this.part1 = part1;
this.part2 = part2;
}
@Override public boolean equals(Object other) {
if (!(other instanceof Key2)) {
return false;
}
// Can't find out the type arguments, unfortunately
Key2 rawOther = (Key2) other;
// TODO: Handle nullity
return part1.equals(rawOther.part1) &&
part2.equals(rawOther.part2);
}
@Override public int hashCode() {
// TODO: Handle nullity
int hash = 23;
hash = hash * 31 + part1.hashCode();
hash = hash * 31 + part2.hashCode();
return hash;
}
// TODO: Consider overriding toString and providing accessors.
}
The more situation-specific types would be slightly simpler as they wouldn't be generic - in particular this would mean you wouldn't need to worry about the type arguments, and you could give the variables better names.
Upvotes: 10