【发布时间】:2014-09-14 20:02:26
【问题描述】:
我遇到了性能问题,因为为了检索某个键的值,我必须检查存储在映射中的每个键是否等于我的测试键。性能问题源于我必须覆盖地图的 get 操作,该操作检查地图是否具有测试密钥。我的键需要某种元组,我使用String[] 来存储两个Strings。这是我的带地图的课程。
public class ClassWithMap {
Map<String[], Double> arrayToDoubleMap;
public ClassWithMap() {
arrayToDoubleMap = new HashMap<String[], Double>() {
@Override
public Double get(Object key) {
String[] stringArray = (String[]) key;
Set<String[]> keySet = this.keySet();
for (String[] tuple : keySet) {
if (tuple[0].equals(stringArray[0]) && tuple[1].equals(stringArray[1])) {
key = tuple;
break;
}
}
return super.get(key);
}
};
}
public Double getDouble(String string1, String string2) {
String[] tuple = { string1, string2 };
return (Double) arrayToDoubleMap.get(tuple);
}
}
这里有一些测试方法。
public static void main(String[] args) {
ClassWithMap map = new ClassWithMap();
String[] tuple1 = { "foo", "bar" };
map.arrayToDoubleMap.put(tuple1, 0.0);
String[] tuple2 = { "fee", "fum" };
map.arrayToDoubleMap.put(tuple2, 1.0);
System.out.println(map.getDouble("fee", "fum"));
}
如果我不覆盖映射声明中的get 操作,我会得到null,因为String[] 键与测试String[] 键不完全相同。
所以我的问题是:有没有比创建一个检查每个键和测试键之间是否匹配的方法更有效的方法来强制此对象等效?
【问题讨论】:
-
你可以创建一个不同的类,称之为StringTuple,它是一个包含两个字符串的对象。您可以通过比较字符串相等性来实现
compareTo()/equals()。 -
你不应该像那样覆盖核心功能(它一定会导致悲伤)。相反,将
String[]包装在一个简单的类中,该类适当地实现equals()和hashcode()。 -
@OliCharlesworth,那么为什么可以在这个新类中覆盖
equals(),但不能在这个地图类中覆盖get()?您如何定义“核心功能”? -
@ijkilchenko:好问题。我想答案是“因为 HashMap.get 不是为了被覆盖而设计的”。可能存在依赖
get以特定方式工作的内部实现细节,您现在可能已经违反了。另一方面,equals非常适合被覆盖。然后你可以争辩说HashMap.get应该标记为final,我同意。 -
@OliCharlesworth,这不一定是我会详述的,但是如果您再次查看我的覆盖,它只会更改随后传递给
super.get()方法的对象。所以我最终不会违反太多。
标签: java oop data-structures map