我有一个要求,我需要将多个决定因素映射到值。
保证给定作业执行中的每组决定因素都是唯一的。要确定的值不必是唯一的,但可能是。
根据作业执行的输入,可以是一个键,也可以是两个键的组合,或者是n
键的组合,它们将映射到单个值。在实践中,n
可能会限制在不超过5个,但有可能超过5个。
每个作业执行将为所有输入设置一定数量的决定因素(即,所有输入将具有2个决定因素,3个决定因素或n个决定因素,并且不会混合)。
一个关键示例:foo --> bar
两个键:foo, bar --> baz
三个键:foo, bar, baz --> hai
在此之前,要求是我只会将两个值映射到另一个值。我创建了一个不可变的Key类,它包含两个成员变量以及equals
和hashCode
的相应覆盖。
public class Key {
String determinant0;
String determinant1;
public Key(String d0, d1) {
determinant0 = d0;
determinant1 = d1;
}
// ..
}
但是,现在我可能正在处理n个值,我想看一下使用列表作为键。
Map<List, String> map = new HashMap<List, String>();
map.put(Arrays.asList("foo", "bar", "baz"), "hai");
String determined = map.get(Arrays.AsList("foo","bar","baz"));
assert (determined.equals("hai"));
这个question提醒我,使用可变对象(如List)作为地图中的键是不好的。但是,在我的应用程序中,密钥只设置一次,永远不会改变。这是question的另一种选择,它强制它是不可变的:
HashMap<List<String>, String> map;
map.put(
// unmodifiable so key cannot change hash code
Collections.unmodifiableList(Arrays.asList("foo", "bar", "baz")),
"hai"
);
此外,我总是可以创建一个类似下面的类来防止列表中的突变:
public class Key {
List<String> determinants;
public Key(List<String> determinants) {
this.determinants = determinants
}
@Override
public boolean equals(Object obj) {
//...
}
@Override
public int hashCode() {
//...
}
}
Key key = new Key(Arrays.asList("foo","bar","baz"));
使用普通数组作为键将不起作用,因为数组的相等方法仅检查标识:
Map<String[], String> map = new HashMap<String[], String>();
String[] key = new String[]{"foo", "bar", "baz"}
map.put(key, "hai");
System.out.println(map.get(key)); // null
可以通过以下方式解决:
public class Key {
String[] determinants;
public Key(String... determinants) {
this.determinants = determinants;
}
@Override
public boolean equals(Object obj) {
//...
}
@Override
public int hashCode() {
//...
}
}
如何将所有决定因素串在一起?
public class Key {
String hash = "";
public Key(String... determinants) {
for (String determinant : determinants) {
hash += determinant + "_";
}
}
@Override
public boolean equals(Object obj) {
//...
}
@Override
public int hashCode() {
//...
}
}
这些解决方案中的哪一个(或我未提出的另一个解决方案)最适合这些要求?
答案 0 :(得分:1)
作为评论,您的问题包含太多细节,可能会更短。现在回答我。
我更喜欢使用完全隐藏类表示的包装类。作为小优化,您可以做的一件事是存储密钥的hashCode,以防止每次都计算它。 equals
方法将被更少地调用(地图中的每次碰撞)并且你不能做很多事情:
public class Key {
private String[] determinants;
private int hashCode;
public Key(String... determinants) {
if (determinants == null || determinants.length == 0) {
throw new IllegalArgumentException("Please provide at least one value");
}
this.determinants = determinants;
this.hashCode = Objects.hash(determinants);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
Key that = (Key) o;
return Arrays.equals(determinants, that.determinants);
}
@Override
public int hashCode() {
return hashCode;
}
}