限制 Java 哈希映射中 get 方法的对象类型

2022-09-04 08:41:23

我已经实例化了我的HashMap,如下所示:

Map<String, Integer> myHashMap = new HashMap<String, Integer>();

的数据类型是 String,因此当我尝试在将 键值保留为 Integer 的映射中插入新的键值对时,它会引发错误。KeyKey

myHashMap.put(1L, "value");

这意味着在 put 方法中,它们限制了 .但是,在使用该方法从映射中获取值时,它不会检查 .因此,如果我写这样的东西,它不会给出编译错误。KeygetKey

myHashMap.get(1L);

我检查了Java Map接口中的方法,其参数类型是,这就是为什么它允许任何对象作为放置方法参数的原因。getObject

V get(Object key)

有没有办法限制我在方法中作为参数传递的数据类型?get

我传递的参数应与我在实例化哈希映射时使用的数据类型具有相同的数据类型。Key


答案 1

它是以这种方式设计的,因为在 get 操作期间,只有 和 用于确定要返回的对象。该方法的实现不检查用作键的对象的类型。equalshashCodeget

在您的示例中,您尝试通过传递长 like 来获取值,首先,具有该值的对象的哈希代码将用于确定要从中查找的存储桶。接下来,的方法用于找出要从中返回值的映射的确切条目。在定义良好的方法中,始终会检查类型:myHashMap.get(1L);Long1Lequalsequals

public boolean equals(Object obj) {
    if (obj instanceof Long) { //here type is checked
        return value == ((Long)obj).longValue();
    }
    return false;
}

因此,如果类型不相等,则该方法将返回,因此也将返回 。equalsfalsegetnull

在某些情况下,例如用作键时,可能会发生使用 say 的实例将项目放入映射的情况,但您可以使用 的实例成功检索相同的值。由于两者都实现了接口。ListArrayListLinkedListList

Map<List<String>, String> myHashMap = new HashMap<>();
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
myHashMap.put(arrayList, "foo");
System.out.println(myHashMap.get(linkedList));

上面的代码将在控制台中输出。foo

这里虽然实现是不同的,但是如果你检查的方法,它只检查类型是否是:equalsArrayListList

public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof List)) { //checking type of super interface
            return false;
        }
        ...
}

对于 .LinkedList


答案 2

我认为,如果在项目中,我们在HashMap中控制类型非常重要,那么我们可以扩展HashMap并强制使用此类而不是像下面的代码那样的HashMap。

我们拥有所有 HashMap 功能,我们应该只使用 getValue 方法而不是 get 方法。

import java.util.HashMap;

public class MyHashMap<K,V> extends HashMap<K,V> {

    public V getValue(K key) {
        return super.get(key);
    }
}

测试类:

 public class Test {
     public static void main(String[] args) {
         MyHashMap<String,Integer> map = new MyHashMap();
     }
 }