在我的程序中,我想使用带有两个键(整数)的 Map。我的第一个想法是以某种方式将整数连接成一个字符串,例如:
String key = k1.toString()+"-"+k2.toString();
这个解决方案对我来说看起来不太好:1)丑陋;2)慢(将数字作为文本处理)。
我在 stackoverflow 上发现了其他方法。它们基于将整数封装在一个类中——一个目的类(MyKey),或更通用的一个(Pair)。
我尝试进行一些速度测试,我的虚拟解决方案似乎是最快的。第一次拍摄后,我尝试将转换整数字符串封装在一个新类(MyString)中,并针对该解决方案运行测试。
地图定义是:
Map<Pair<Integer,Integer>,String> map1 = new HashMap<>();
Map<MyKey,String> map2 = new HashMap<>();
Map<String,String> map3 = new HashMap<>();
Map<MyString,String> map4 = new HashMap<>();
测试结果是(运行多次,似乎稳定):
map: put+get=total
1: 52+154=206
2: 29+77=106
3: 23+49=72
3: 17+55=72
带字符串的解决方案更快。字符串键的直接连接在搜索时更快,在输入时更慢。
我的问题是:
1) 为什么使用 String 的解决方案更快?(一次调用 hashCode()?)
2) 有什么理由不应该使用 String 的解决方案吗?
附加信息:
地图中的记录数约为 6000 条。
测试还试图获取许多不存在的键的值。它会改变测试结果吗?
在我的程序中,我生成 boolean[N] 的排列,其中 M 值为真。一次,我得到某个 N,M 的结果;我想保存它们以备不时之需。
这是我的示例中使用的类的完整代码:
class Pair<L,R> {
private final L left;
private final R right;
public Pair(L left, R right) {
this.left = left;
this.right = right;
}
public L getLeft() { return left; }
public R getRight() { return right; }
@Override
public int hashCode() { return left.hashCode() ^ right.hashCode(); }
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (!(o instanceof Pair)) return false;
Pair pairo = (Pair) o;
return this.left.equals(pairo.getLeft()) &&
this.right.equals(pairo.getRight());
}
}
class MyKey {
public Integer k1;
public Integer k2;
public MyKey(Integer k1, Integer k2) {
this.k1 = k1;
this.k2 = k2;
}
@Override
public int hashCode() {
return k1.hashCode() + 17 * k2.hashCode();
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null || !(o instanceof MyKey)) {
return false;
}
MyKey cp = MyKey.class.cast(o);
return k1.equals(cp.k1) && k2.equals(cp.k2);
}
}
class MyString {
private String value;
public MyString(Integer k1, Integer k2) {
value=k1+"-"+k2;
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public boolean equals(Object o) {
return o.equals(value);
}
}