HashMap和HashSet中hashCode()和equals()方法重写的问题
2016-04-09 12:33
471 查看
散列码
当我们需要使用自己定义的类作为HashMap中的key的时候,或者希望使用HashSet保证集合中不含有重复的对象,这是需要重写hashCode方法。具体原因,先来看一下当向HashMap中插入时所做的操作。1 public V put(K key, V value) { 2 if (key == null) 3 return putForNullKey(value); 4 int hash = hash(key.hashCode()); 5 int i = indexFor(hash, table.length); 6 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 7 Object k; 8 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {//链接方法处理冲突 9 V oldValue = e.value; 10 e.value = value; 11 e.recordAccess(this); 12 return oldValue; 13 } 14 } 16 modCount++; 17 addEntry(hash, key, value, i); 18 return null; 19 }
void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; 2 table[bucketIndex] = new Entry<K,V>(hash, key, value, e);//bucketIndex是插入当前链表的位置 3 if (size++ >= threshold) 4 resize(2 * table.length); 5 }
1.在类的内部维护着一个哈希表,使用key的地址计算出索引的位置。
2.当前索引位置是否存在hashcode相同且key相同的元素,若有,则用新值覆盖掉。
(这里有key的比较用了equals方法,equals方法默认是比较的引用的值,而我们需要的是对象的内容相等即视为这两个对象相等,而不是他们地址相等,实际上当我们new两个对象时,他们的地址也不可能相等。这也是为什么equals也要重写的原因吧)
3.插入到i上,这里用的是链接方法处理的冲突,即哈希值相同的对象存放在index为i的一个链表里。(下图)
另外,String类比较特殊,当它作为key时不用重写,是因为如果程序中有多个String对象都包含相同的字符串序列时,这些String对象都映射到了同一块内存区域,所以虽然new 的String实例是独立的,但他们使用hashCode生成的结果应该是相同的。(Thinking In java P495)。
重写hashCode()和equals方法
在eclipse或myeclipse中,IDE会帮我们重写,快捷键shift+alt+s+h
重写hashCode()和equals
shift+alt+s+s
重写toString()
在下面的代码中,说明hashset在重写后不能加入重复对象,若不重写,s.size()的值应为2
public class HashTest{ public static void main(String[] args){ Set<K> s = new HashSet<K>(); s.add(new K(1,2)); s.add(new K(1,2)); System.out.println(s.size()); } } class K{ int a; int b; K(int a, int b){ this.a = a; this.b = b; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + a; result = prime * result + b; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; K other = (K) obj; if (a != other.a) return false; if (b != other.b) return false; return true; } }
1.使用key的地址计算出索引的位置
相关文章推荐
- centOS 操作记录二
- centOS 操作记录二
- centOS 操作记录二
- centOS 操作记录二
- centOS 操作记录二
- spring classpath和filesystem
- 关于unicode的学习
- 信号signal
- memcached实战系列(六)理解Memcached的数据存储方式
- 16 个 Linux 服务器监控命令
- memcached实战系列(六)理解Memcached的数据存储方式
- 杭州电子科技大学(HDU)ACM 刷题---------字符串处理之1062
- 浅谈runtim的归档和解档
- 【二维费用背包】HDU3496Watch The Movie
- 结对项目——四则运算
- 机器学习在金融大数据风险建模中的应用
- 别人犯错给自己的警醒(二):人取得成就之后很容易膨胀
- Android学习笔记(Google官方教程)(三)
- NDK开发步骤
- sorted 函数