hashCode和equals_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > hashCode和equals

hashCode和equals

 2016/5/12 5:33:48  臻是二哥  程序员俱乐部  我要评论(0)
  • 摘要:最近在复习的时候,又重新的理解了下equals()和hashCode().equals()用于判断两个对象是否相等,这是大家公认的。hashCode()被设计是用来使得哈希容器能高效的工作。为什么这么说?在java中,有一些哈希容器,比如Hashtable,HashMap等等。当我们调用这些类的诸如get(Objectobj)方法时,容器的内部肯定需要判断一下当前对象obj在容器中是否存在,以便进行后续的操作。判断是够存在,肯定是要比较两个对象是否相等,我们"应该"要使用equals(
  • 标签:has Hash
最近在复习的时候,又重新的理解了下equals()和hashCode().
equals()用于判断两个对象是否相等,这是大家公认的。
hashCode()被设计是用来使得哈希容器能高效的工作。

为什么这么说?在java中,有一些哈希容器,比如Hashtable,HashMap等等。当我们调用这些类的诸如get(Object obj)方法时,容器的内部肯定需要判断一下当前对象obj在容器中是否存在,以便进行后续的操作。判断是够存在,肯定是要比较两个对象是否相等,我们"应该"要使用equals()才是正确的。

但是如果哈希容器中的元素有很多的时候,使用equals()必然会很慢。这个时候我们想到一种替代方案就是hashCode()。hashCode()返回一个int类型,比较起来要快很多。但这也造成了一个问题,就是一个判定两个对象事实上存在两个标准?当然不是这样的,正如在文章开头所说,hashCode()被设计用来使得哈希容器中能高效的工作。也只有在哈希容器中,才使用hashCode()来进行比较对象是否相等,而且还是弱的比较。

当我们调用哈希容器的get(Object obj)方法时,他会首先查看当前容器中是够存在相同的哈希值,如果不存在,那么返回null。如果存在,再调用当前对象的equals()方法比较一下看哈希处的对象是否和要查找的对象为相同的对象,如果不是,那么返回null。如果是,说明当前哈希容器存在相应的值,返回该哈希处的对象。

这样hashCode()方法就提高了哈希容器的效率,这就是hashCode()存在的意义。我们可以把hashCode()相等看成是两个对象相等的必要非充分条件,equals()相等才是充分条件。因此,在自定义一个类的时候,我们必须要同时重写equals()和hashCode(),并且必须保证:
1 如果两个对象的equals()相等,那么他们的hashCode()必定相等。
2 如果两个对象的hashCode()不相等,那么他们的hashCode()必定不等。


class="java">import java.util.HashMap;


public class Demo {
	public static void main(String[] args) throws Exception{
		Person person=new Person("xyz",22);
		HashMap<Person,Integer> hashMap=new HashMap<Person,Integer>();
		hashMap.put(person, 1);
		System.out.println(hashMap.get(new Person("xyz",22)));
	}
}
class Person{
	private String name;
	private int age;
	public Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

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

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this==obj)
			return true;
		if(obj instanceof Person){
			Person person=(Person) obj;
			if(this.age==person.getAge() && this.name.equals(person.getName()) )
				return true;
		}
		return false;
	}
//	@Override
//	public int hashCode() {
//		return this.name.hashCode()*10+this.age;
//	}
}


上面的代码注释掉hashCode()前后的运行结果不同,当注释掉hashCode()的时候,person和后来新建的Person虽然equals是同一对象,但HashMap容器内部比较hashCode()的时候会认为他们是不同元素。

因此,牢记一点,当我们重写equals()方法时候一定要重写hashCode()方法。


下面我们来看看String类的equals方法和hashCode方法:
 public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
 public int hashCode() {
        int h = hash;//默认是0
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;//String的哈希值由组成该String的字符串的ASCII值根据相应的规则加和
    }

发表评论
用户名: 匿名