重写equals()方法时,需要同时重写hashCode()方法

package com.wangzhu.map;

import java.util.HashMap;

/**
 * hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,<br/>
 * 这样的散列集合包括HashSet、HashMap以及HashTable。<br/>
 * 能否可以直接根据hashCode值判断两个对象是否相等呢?<br/>
 * 答案:肯定是不可以的,因为不同的对象可能会生成相同的hashCode值。<br/>
 * 虽然不能根据hashCode值判断两个对象是否相等,但是可以直接根据hashCode值判断两个对象不等,<br/>
 * 如果两个对象的hashCode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,则必须通过equals方法。<br/>
 * 也就是说对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashCode值必定相等。<br/>
 * 如果equals方法得到的结果为,则两个对象的hashCode值不一定不同; <br/>
 * 如果两个对象的hashCode值不等,则equals方法得到的结果必为;<br/>
 * 如果两个对象的hashCode值相等,则equals方法得到的结果未知。<br/>
 * 
 * @author wangzhu
 * @date 2015-2-1下午11:22:42
 * 
 */
public class DemoMap2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Student stu = new Student(21, "John");
        HashMap<Student, Integer> map = new HashMap<Student, Integer>();
        map.put(stu, 1);
        System.out.println(map.get(stu));// 1
        System.out.println(map.get(new Student(21, "John")));// 1
        /**
         * 若Student只重写equals方法而没有没有重写hashCode方法时,则输出为null
         */

        stu.setAge(22);
        System.out.println(map.get(stu));// null
        /**
         * 在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,<br/>
         * 那么对这同一个对象调用多次, hashCode方法必须始终如一地返回同一个整数。<br/>
         * 
         * 设计hashCode()时最终稿的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。<br/>
         * 如果在将一个对象用put()添加进HashMap时产生一个hashCode值,而用get()取出时却产生另一个hashCode值,<br/>
         * 那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,<br/>
         * 因为此数据变化时,hashCode() 方法就会生成一个不同的散列码。<br/>
         */
    }

}

class Student {
    int age;
    String name;

    public Student(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = (prime * result) + age;
        result = (prime * result) + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    /**
     * 重写时,需要让equals方法与hashCode方法始终在逻辑上保持一致性。
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        Student other = (Student) obj;
        if (age != other.age) {
            return false;
        }
        if (name == null) {
            if (other.name != null) {
                return false;
            }
        } else if (!name.equals(other.name)) {
            return false;
        }
        return true;
    }

}

 

下面是HashMap中的put方法【JDK1.6】

    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

备注:put方法是用来向HashMap中添加新的元素。从put方法的具体实现可知,其会先调用hashCode方法得到该元素的hashCode值【经过处理的】,然后查看其是否存在于table数组中,如果存在则调用equals方法来确定是否是存在该元素;如果存在,则更新value值,否则将新的元素添加到HashMap中。

 

下面是HashMap中的get方法【JDK1.6】

 public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

备注:get方法是用来将HashMap中对应Key的值Value取出来。从get方法的具体实现可知,其会先调用hashCode方法得到该元素的hashCode值,然后查看其在table数组中是否存在,如果存在则调用equals方法来确定是Key对应的元素,并返回其Value,否则返回null。

 

posted @ 2015-02-01 23:42  qingyezhu  阅读(323)  评论(0编辑  收藏  举报