英文:
Using an interface as a key in a hashmap
问题
我尝试使用接口作为hashMap
中的键,以便为多种类型的键使用1个映射。以下似乎有效。
interface Foo {
void function();
}
static class Bar implements Foo {
private int id;
public Bar(int id) {
this.id = id;
}
@Override
public void function() {
System.out.println("this is bar");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Bar bar = (Bar) o;
return id == bar.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
public static Map<Foo, Integer> map = new HashMap<>();
static class Baz implements Foo {
String name;
public Baz(String name) {
this.name = name;
}
@Override
public void function() {
System.out.println("this is Baz");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Baz baz = (Baz) o;
return name.equals(baz.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
public static void main(String[] args) {
Bar bar = new Bar(123);
Baz baz = new Baz("some name");
map.put(bar, 10);
map.put(baz, 20);
System.out.println(map.get(bar));
}
我不确定的是是否有一些特殊情况会破坏这个映射?是否有一种情况下,使用接口作为键会出现问题?我是否可以使用泛型更简单地实现它?
英文:
I tried to use an interface as a key in a hashMap
in order to have 1 map for multiple types of keys. The following seems to work.
interface Foo {
void function();
}
static class Bar implements Foo {
private int id;
public Bar(int id) {
this.id = id;
}
@Override
public void function() {
System.out.println("this is bar");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Bar bar = (Bar) o;
return id == bar.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
public static Map<Foo, Integer> map = new HashMap<>();
static class Baz implements Foo {
String name;
public Baz(String name) {
this.name = name;
}
@Override
public void function() {
System.out.println("this is Baz");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Baz baz = (Baz) o;
return name.equals(baz.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
public static void main(String[] args) {
Bar bar = new Bar(123);
Baz baz = new Baz("some name");
map.put(bar, 10);
map.put(baz, 20);
System.out.println(map.get(bar));
}
What I am not sure about is if there is some corner case that would break this map?
Is there a case that having an interface as a key would break down? Could I have done it simpler using generics?
答案1
得分: 2
代码部分不要翻译,只返回翻译好的部分:
唯一有点不同寻常的是equals方法必须比较Bar和Baz对象。当一个Map只包含一种类型的对象时,在equals方法中的检查this.getClass() == that.getClass
永远不会返回false。不过你已经正确地实现了这一点,所以不用担心。
可能会出现比预期更多的哈希碰撞。想象一下,你有两个类都有一个int id字段,并且使用Objects.hash(id)
实现了hashCode - 现在不同类的具有相同ID的对象具有相同的哈希码。如果这是预期的用例,你可以以每个类特定的方式扰动哈希,例如通过将类特定的常量混合到哈希中:
@Override
public int hashCode() {
return Objects.hash(1, id);
}
...
@Override
public int hashCode() {
return Objects.hash(2, name);
}
英文:
The only thing that's slightly out of the ordinary is that the equals methods have to compare Bar and Baz objects. When a Map only has one type of objects, the check this.getClass() == that.getClass
in equals method never returns false. You have implemented this correctly though, so you don't have anything to worry about.
You may get more hash collisions than you expect. Imagine you have two classes that both have an int id field and implement hashCode with Objects.hash(id)
- now objects of different classes with the same ID have the same hash code. If this use case is expected, you can perturb the hash in a way unique to each class, for example by mixing a class-specific constant to the hash:
@Override
public int hashCode() {
return Objects.hash(1, id);
}
...
@Override
public int hashCode() {
return Objects.hash(2, name);
}
答案2
得分: 1
理论上可能存在问题,可能会因为hashCode
的不同实现导致更多的哈希碰撞,从而导致性能下降,因此您需要小心,并使用实际数据进行测试。除此之外,这是一个有效的用例。
英文:
In theory there could be problems with potentially more hash collisions leading to bad performance due to different implementations of hashCode
, so you need to be careful, and test it with the real data. Other than that it is a valid use case.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论