`
xm_king
  • 浏览: 392681 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
Group-logo
Spring技术内幕读书笔...
浏览量:15374
社区版块
存档分类
最新评论

HashCode和equals方法深度分析

    博客分类:
  • JAVA
阅读更多

 

         在往HashSet集合中放数据的时候,由于HashSet底层是用HashMap中的Key属性存储的,所以是不能重复的,那他如何判断其不是重复的元素呢.这个时候他判断有两步.

       1.调用元素的hashcode 方法,判断两对象的hashCode 是否相等,如果不相等,则认为两对象不相等,结束.如果相等,则转入equals 方法进行判断.

       2.如果equals 方法返回true则,是相等的.如果返回false则是不相等的.结束.这里是最终结果.

       总的归纳是如果在调用hashCode 方法时判断了对象不相等那就有了结论.不用调用equals 方法了

 

 如要以上推论成立,需要验证四个结论:

        1.这个hashCode 方法中返回的结果是永远也不相等的,因此会调用equals 方法进行判断,结果是所有元素都打印出来了.

        2.hashCode 方法不变,修改equals 方法,让其总返回false,结果和1一样.

---->以上两点成立的话,说明hashCode 方法返回的值不相等的话,结果就与equals 方法无关了.

        3.当把hashCode 方法中返回数改成一常量时,equas方法总return false,结果是返回第一个元素;

        4.当把hashCode 方法中返回数改成一常量时,equas方法总return ture 结果返回全部元素.

----->以上两点成立的话,说明hashCode 方法返回的值相等的话,结果有equals 方法控制.

import java.util.HashSet;
import java.util.Iterator;
public class TestHashSet {
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  HashSet hs  = new HashSet();
  String a="123";
  hs.add(new Element(a,"mengchao"));
  hs.add(new Element(a,"mengchao"));
  hs.add(new Element("1234","mengchao3"));
  Iterator it=hs.iterator();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
 }
}

class Element{
 
 private String num;
 private String name;
 static int i=0;
 public Element(String num,String name){
  this.num=num;
  this.name=name;
 }
 
 public String toString(){
  return "学号为:"+num+";————名字为"+name;
 }
 public int hashCode(){
  return i++;
 }
 public boolean equals(Object o){
  Element os = (Element)o; 
  return true;
 }
}

结果:
学号为:1234;————名字为mengchao3
学号为:123;————名字为mengchao
学号为:123;————名字为mengchao
 

       将equals 方法中  return true; 改成  return false;结果还是一样.

import java.util.HashSet;
import java.util.Iterator;

public class TestHashSet {
 
 

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  HashSet hs  = new HashSet();
  String a="123";
  hs.add(new Element(a,"mengchao"));
  hs.add(new Element(a,"mengchao"));
  hs.add(new Element("1234","mengchao3"));
  
  Iterator it=hs.iterator();
  
  while(it.hasNext())
  {
   System.out.println(it.next());
  }

 }

}


class Element{
 
 private String num;
 private String name;
 //static int i=0;
 public Element(String num,String name){
  this.num=num;
  this.name=name;
 }
 
 public String toString(){
  return "学号为:"+num+";————名字为"+name;
 }
 public int hashCode(){
  return 3;
 }
 public boolean equals(Object o){
  Element os = (Element)o; 
  return true;
  
 }
}
运行结果:

学号为:123;————名字为mengchao
 

        将equals 方法中  return true; 改成  return false;

 

运行结果:

学号为:1234;————名字为mengchao3
学号为:123;————名字为mengchao
学号为:123;————名字为mengchao

       在Object类中定义的几个hashCode约定如下:
       1. 在同一应用中,一个对象的hashCode函数在equals函数没有更改的情况下,无论调用多少次,它都必须返回同一个整数。
       2. 两个对象如果调用equals函数是相等的话,那么调用hashCode函数一定会返回相同的整数。
       3. 两个对象如果调用equals函数是不相等的话,那么调用hashCode函数不要求一定返回不同的整数。

         补充一点我自己的看法,拿HashMap来举例,

       在HashMap中保存元素的值是一个 transient Entry[] table,也就是一个数组。在这里要特别注意Entry的元素,在Entry中它有一个属性next,记录了和本节点具有相同的Hash码的对象。但是它们的Equals方法返回的是false。这也解释了为什么先去判断HashCode值,还要再去判断equals方法了。

          在往HashMap中加入数据的过程是这样的,首先要根据key的hashcode值,根据一定的散列算法,找到对应table上的位置,如果该位置已经有value存在了,那么,判断旧value的key和新插入值的key的equals方法是否相等,如果相等,把旧value替换成新插入值。key不变(因为hashcode和equals都相等,HashMap就认为这两个key是相等的)。如果不相等,则将旧value的entry的next属性设置为新value对应的entry属性(实际上这就是解决hash冲突的一种方法)。

            从HashMap中取出元素的过程和上面刚好相反,在这里就不叙述了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics