在Java HashMap中限制get方法的对象类型

时间:2019-04-22 07:04:03

标签: java hashmap

我已经这样实例化了HashMap:

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

Key的数据类型为String,因此当我尝试在地图中插入一个新的键值对时,将Key保留为Integer,则会引发错误。

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

这意味着在put方法中,他们限制了Key的数据类型。但是,在使用get方法从映射中获取值时,它并没有检查Key的数据类型。因此,如果我写这样的东西,它不会给出编译错误。

myHashMap.get(1L);

我在Java Map界面中检查了get方法,其参数类型为Object,因此这就是为什么它允许将任何Object用作put方法参数的原因。

V get(Object key)

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

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

2 个答案:

答案 0 :(得分:17)

以这种方式设计,因为在获取操作期间,仅使用equalshashCode来确定要返回的对象。 get方法的实现不检查用作键的对象的类型。

在您的示例中,您尝试通过传递类似myHashMap.get(1L);的长整数来获取值,首先,对象Long的哈希码具有值1L将用于确定从中寻找水桶。接下来,使用 key equals方法来查找要从中返回值的映射的确切条目。并且在定义明确的equals方法中,始终会检查类型:

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

因此,如果类型不相等,则equals方法将返回false,因此get也将返回null

在某些情况下,例如使用List作为键时,可能会发生这样的情况:您使用诸如ArrayList的实例在地图上放置了一个项目,但可以成功地使用检索相同的值LinkedList的实例。由于两者都实现了List接口。

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中输出。

尽管实现方式不同,但是如果您检查equals的{​​{1}}方法,则仅检查类型是否为ArrayList

List

public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof List)) { //checking type of super interface return false; } ... } 也是如此。

答案 1 :(得分:4)

我认为,如果在我们控制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();
     }
 }