Java 如何实现具有多个键的 Map?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/822322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement a Map with multiple keys?
提问by ivan_ivanovich_ivanoff
I need a data structure which behaves like a Map,
but uses multiple (differently-typed) keys to access its values.
(Let's not be too general, let's say twokeys)
我需要一个数据结构,它的行为类似于 Map,但使用多个(不同类型的)键来访问其值。
(不要太笼统,先说两个键)
Keys are guaranteed to be unique.
键保证是唯一的。
Something like:
就像是:
MyMap<K1,K2,V> ...
With methods like:
使用以下方法:
getByKey1(K1 key)...
getByKey2(K2 key)...
containsKey1(K1 key)...
containsKey2(K2 key)...
Do you have any suggestions?
你有什么建议吗?
The only thing I can think of is:
Write a class which uses two Maps internally.
我唯一能想到的是:
编写一个在内部使用两个 Map 的类。
EDITSome people suggest me to use a tuple, a pair, or similar as a key for
Java's Map, but this would not workfor me:
I have to be able, as written above, to search values by only one of the two keys specified.
Maps use hash codes of keys and check for their equality.
编辑有些人建议我使用tuple、pair或类似的作为 Java Map 的键,但这对我不起作用:
如上所述,我必须能够仅通过两个键中的一个来搜索值指定的。
地图使用键的哈希码并检查它们的相等性。
采纳答案by Jeremy Huiskamp
Two maps. One Map<K1, V>
and one Map<K2, V>
. If you must have a single interface, write a wrapper class that implements said methods.
两张地图。一个Map<K1, V>
和一个Map<K2, V>
。如果您必须有一个接口,请编写一个实现上述方法的包装类。
回答by moinudin
Define a class that has an instance of K1 and K2. Then use that as class as your key type.
定义一个具有 K1 和 K2 实例的类。然后将其用作类作为您的密钥类型。
回答by Carl Manaster
See Google Collections. Or, as you suggest, use a map internally, and have that map use a Pair. You'll have to write or find Pair<>; it's pretty easy but not part of the standard Collections.
请参阅Google 收藏集。或者,按照您的建议,在内部使用地图,并让该地图使用 Pair。你必须写或找到 Pair<>; 这很简单,但不是标准集合的一部分。
回答by duffymo
Sounds like a Python tuple. Following in that spirit, you can create an immutable class of your own devising that implements Comparable and you'll have it.
听起来像一个 Python 元组。本着这种精神,您可以创建一个自己设计的不可变类来实现 Comparable,您将拥有它。
回答by Uri
Sounds like your solution is quite plausible for this need, I honestly don't see a problem with it if your two key types are really distinct. Just makes ure you write your own implementation for this and deal with synchronization issues if needed.
听起来您的解决方案非常适合这种需求,老实说,如果您的两种键类型确实不同,我认为它没有问题。只需确保您为此编写自己的实现并在需要时处理同步问题。
回答by Dima
回答by ykaganovich
I can see the following approaches:
我可以看到以下方法:
a) Use 2 different maps. You can wrap them in a class as you suggest, but even that might be an overkill. Just use the maps directly: key1Map.getValue(k1), key2Map.getValue(k2)
a) 使用 2 张不同的地图。您可以按照您的建议将它们包装在一个类中,但即使这样也可能有点矫枉过正。直接使用地图:key1Map.getValue(k1), key2Map.getValue(k2)
b) You can create a type-aware key class, and use that (untested).
b) 您可以创建一个类型感知键类,并使用它(未经测试)。
public class Key {
public static enum KeyType { KEY_1, KEY_2 }
public final Object k;
public final KeyType t;
public Key(Object k, KeyType t) {
this.k = k;
this.t= t;
}
public boolean equals(Object obj) {
KeyType kt = (KeyType)obj;
return k.equals(kt.k) && t == kt.t;
}
public int hashCode() {
return k.hashCode() ^ t.hashCode();
}
}
By the way, in a lot of common cases the space of key1
and the space of key2
do not intersect. In that case, you don't actually need to do anything special. Just define a map that has entries key1=>v
as well as key2=>v
顺便说一句,在很多常见情况下, 的空间key1
和 的空间key2
不相交。在这种情况下,您实际上不需要做任何特别的事情。只需定义一个具有条目key1=>v
以及key2=>v
回答by ivan_ivanovich_ivanoff
Proposal, as suggested by some answerers:
提案,正如一些回答者所建议的:
public interface IDualMap<K1, K2, V> {
/**
* @return Unmodifiable version of underlying map1
*/
Map<K1, V> getMap1();
/**
* @return Unmodifiable version of underlying map2
*/
Map<K2, V> getMap2();
void put(K1 key1, K2 key2, V value);
}
public final class DualMap<K1, K2, V>
implements IDualMap<K1, K2, V> {
private final Map<K1, V> map1 = new HashMap<K1, V>();
private final Map<K2, V> map2 = new HashMap<K2, V>();
@Override
public Map<K1, V> getMap1() {
return Collections.unmodifiableMap(map1);
}
@Override
public Map<K2, V> getMap2() {
return Collections.unmodifiableMap(map2);
}
@Override
public void put(K1 key1, K2 key2, V value) {
map1.put(key1, value);
map2.put(key2, value);
}
}
回答by Kevin Peterson
Depending on how it will be used, you can either do this with two maps Map<K1, V>
and Map<K2, V>
or with two maps Map<K1, V>
and Map<K2, K1>
. If one of the keys is more permanent than the other, the second option may make more sense.
根据它的使用方式,您可以使用两个地图Map<K1, V>
和Map<K2, V>
或两个地图Map<K1, V>
和来执行此操作Map<K2, K1>
。如果其中一个键比另一个更持久,则第二个选项可能更有意义。
回答by Logan Capaldo
I'm still going suggest the 2 map solution, but with a tweest
我仍然会建议 2 地图解决方案,但有推文
Map<K2, K1> m2;
Map<K1, V> m1;
This scheme lets you have an arbitrary number of key "aliases".
这个方案让你有任意数量的键“别名”。
It also lets you update the value through any key without the maps getting out of sync.
它还允许您通过任何键更新值,而不会导致映射不同步。