你的位置:首页 > 软件开发 > Java > HashMap的key可以是可变的对象吗???

HashMap的key可以是可变的对象吗???

发布时间:2015-09-15 18:00:04
大家都知道,HashMap的是key-value(键值对)组成的,这个key既可以是基本数据类型对象,如Integer,Float,同时也可以是自己编写的对象,那么问题来了,这个作为key的对象是否能够改变呢?或者说key能否是一个可变的对象?如果可以该HashMap会怎么样?可 ...

  大家都知道,HashMap的是key-value(键值对)组成的,这个key既可以是基本数据类型对象,如Integer,Float,同时也可以是自己编写的对象,那么问题来了,这个作为key的对象是否能够改变呢?或者说key能否是一个可变的对象?如果可以该HashMap会怎么样?

可变对象

  可变对象是指创建后自身状态能改变的对象。换句话说,可变对象是该对象在创建后它的哈希值(由类的hashCode()方法可以得出哈希值)可能被改变

  为了能直观的看出哈希值的改变,下面编写了一个类,同时重写了该类的hashCode()方法和它的equals()方法【至于为什么要重写equals方法可以看博客:http://www.cnblogs.com/0201zcr/p/4769108.html】,在查找和添加(put方法)的时候都会用到equals方法。

  在下面的代码中,对象MutableKey的键在创建时变量 i=10 j=20,哈希值是1291。

  然后我们改变实例的变量值,该对象的键 i 和 j 从10和20分别改变成30和40。现在Key的哈希值已经变成1931。

  显然,这个对象的键在创建后发生了改变。所以类MutableKey是可变的。

  让我们看看下面的示例代码:

public class MutableKey {    private int i;    private int j;     public MutableKey(int i, int j) {        this.i = i;        this.j = j;    }     public final int getI() {        return i;    }     public final void setI(int i) {        this.i = i;    }     public final int getJ() {        return j;    }     public final void setJ(int j) {        this.j = j;    }     @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + i;        result = prime * result + j;        return result;    }     @Override    public boolean equals(Object obj) {        if (this == obj) {            return true;        }        if (obj == null) {            return false;        }        if (!(obj instanceof MutableKey)) {            return false;        }        MutableKey other = (MutableKey) obj;        if (i != other.i) {            return false;        }        if (j != other.j) {            return false;        }        return true;    }}

   只要MutableKey 对象的成员变量i或者j改变了,那么该对象的哈希值改变了,所以该对象是一个可变的对象。

HashMap如何存储键值对

  HashMap底层是使用Entry对象数组存储的,而Entry是一个单项的链表。当调用一个put()方法将一个键值对添加进来是,先使用hash()函数获取该对象的hash值,然后调用indexFor方法查找到该对象在数组中应该存储的下标,假如该位置为空,就将value值插入,如果该下标出不为空,则要遍历该下标上面的对象,使用equals方法进行判断,如果遇到equals()方法返回真的则进行替换,否则将其插入,源码详解可看:http://www.cnblogs.com/0201zcr/p/4769108.html。

  查找时只需要查询通过key值获取获取hash值,然后找到其下标,遍历该下标下面的Entry对象即可查找到value。【具体看下面源码及其解释】

在HashMap中使用可变对象作为Key带来的问题

  如果HashMap Key的哈希值在存储键值对后发生改变,Map可能再也查找不到这个Entry了

public V get(Object key)  {  // 如果 key 是 null,调用 getForNullKey 取出对应的 value   if (key == null)    return getForNullKey();  // 根据该 key 的 hashCode 值计算它的 hash 码  int hash = hash(key.hashCode());  // 直接取出 table 数组中指定索引处的值,  for (Entry<K,V> e = table[indexFor(hash, table.length)];    e != null;    // 搜索该 Entry 链的下一个 Entr     e = e.next)     // ①  {    Object k;    // 如果该 Entry 的 key 与被搜索 key 相同    if (e.hash == hash && ((k = e.key) == key      || key.equals(k)))      return e.value;  }  return null;  }  

原标题:HashMap的key可以是可变的对象吗???

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录