【发布时间】:2012-06-03 00:14:54
【问题描述】:
我想创建一个有两个键的地图:
map.put (key1,key2,value1);// Insert into map
map.get(key1,key2); // return value1
我正在研究 multikeyMap,但我不知道该怎么做
【问题讨论】:
标签: java data-structures map arraylist linked-list
我想创建一个有两个键的地图:
map.put (key1,key2,value1);// Insert into map
map.get(key1,key2); // return value1
我正在研究 multikeyMap,但我不知道该怎么做
【问题讨论】:
标签: java data-structures map arraylist linked-list
不幸的是,Java 不支持语言级别的元组,因此您必须使用像这里的一些答案中显示的那样的临时结构。这会导致大量的样板和代码重复。
Functional Java 具有对元组的库支持。适合这里的类是P2。该名称的意思是“具有 2 个元素的产品”。 (产品只是复合类型的代数术语。)该库支持最多 8 个元素的元组。 P{n} 类覆盖所有必要的方法
有一个名为P 的类,它提供了一个静态工厂方法p 用于构造元组。
用法:
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");
【讨论】:
如果您总是想通过 key1 和 key2 一起访问,您可以将它们与分隔符连接在一起作为键并使用法线贴图。
【讨论】:
如果您可以使用外部库,Guava 提供的正是 Table<R, C, V>,将两个键分别称为“行”和“列”。 (披露:我为 Guava 做出了贡献。)
【讨论】:
您可以考虑使用 Guava 的 Table 实现之一。来自文档:
关联有序键对的集合,称为行键 和一个列键,只有一个值。一个表可能是稀疏的,有 只有一小部分行键/列键对拥有 对应的值。
【讨论】:
怎么样
class Key{
private final String key1;
private final String key2;
//accessors + hashcode + equals()
}
和
Map<Key, Value> map
【讨论】:
听起来您只需要一个由两个值创建的键。您可能会发现这两个值自然应该被封装到另一种类型中——或者您可以创建一个Key2<K1, K2> 类型。 (这里的命名允许Key3、Key4 等。不过我不鼓励你走得太远。)
对于介于两者之间的东西,您可以在真正需要的类中创建一个私有静态类(如果它只是一个内部实现细节)。如果它不是自然封装(例如,它类似于“名称和人口”,在此特定场景之外没有意义),那么在保留有意义的属性名称方面会很好,但不会公开。
在任何这些情况下,您最终都会得到一个新类型,其中包含两个最终变量,它们在构造函数中初始化,并且对equals 和hashCode 都有贡献。例如:
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.
}
更多特定于情况的类型会稍微简单一些,因为它们不是通用的 - 特别是这意味着您无需担心类型参数,并且您可以为变量提供更好的名称。
【讨论】:
为什么不将 key 映射到 String 并连接 key1+key2
【讨论】: