1、什么是哈希码(HashCode)

在Java中,哈希码代表对象的特征。例如对象

Java代码

1. String str1 = “aa”, str1.hashCode= 3104  
2. String str2 = “bb”, str1.hashCode= 3106  
3. String str3 = “aa”, str1.hashCode= 3104


根据HashCode由此可得出str1!=str2,str1==str3


哈希码产生的依据:

哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。


下面给出几个常用的哈希码的算法。


1:Object类的hashCode.返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。

2:String类的hashCode.根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串内容相同,返回的哈希码也相同。

3:Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。由此可见,2个一样大小的Integer对象,返回的哈希码也一样。


2、equals方法在hibernate中的应用。


equals方法是默认的判断2个对象是否相等的方法,在Object类里有实现,判断的是2个对象的内存地址。在hibernate中,不允许存在同类对象中有2个一样的实例。hibernate通过equals方法做判断。如:


Java代码

1. User u1 = new User(“张三”);   
2. User u2 = new User(“李四”);  
3. User u3 = new User(“张三”);



按照项目需求,用户只要名字相同,就表示同一个用户,所以我们认为,u1和u3是同一个人,同一个对象。但是因为u1,u2,u3三者的内存地址都各不相同,所以hibernate会认为这是3个不同的对象。这与我们假设的出了矛盾。


因此,我们将覆盖User的equals方法。


Java代码

    1. public class User{  
    2. private String userName;  
    3.   
    4. //get ,set方法省  
    5. //覆盖Object里的equals方法  
    6. public boolean equals(Object arg0){  
    7. if(!(arg0 instanceof User)){  
    8. return false;  
    9. }  
    10. User user = (User)arg0;  
    11. //如果名字相同,则表示属于同一个对象。  
    12. if(user.getName().equals(this.getName)){  
    13. return true;  
    14. }else{  
    15. return false;  
    16. }  
    17.    }


    这样hibernate在插入数据的时候,如果传过来一个叫”张三”的用户,hibernate会先判断有没有叫“张三”的用户,如果没有,就允 许插入,如果有,就不允许插入。这样做可以保证数据的高度一致性,不同的项目有不同的需求,所以要根据自己的需求来覆盖equlas方法。


    3、为什么不按主键来判断

    因为主键是在插入数据进数据库之后才产生的,在一个对象还没有被持久化的时候,它是没有主键的,所以hibernate无法根据主键判断它是否有相同数据。


    equlas和HashCode的关系。


    在hibernate中,它认为2个对象只要equlas返回true,那么hashCode一定相等。


    但是实际情况呢?

    Java代码

    1. User u1 = new User(“张三”);  
    2. User u2 = new User(“张三”);



    由于我们重写了User的equlas方法,所以

    u1.equlas(u2);返回true

    但是,User并没有重写hashCode方法,它用的是Object类的hashCode方法,所以

    u1.hashCode = 31050006

    u2.hashCode = 31587890

    两者的hashCode并不相等。违背了hibernate的原则


    由此hibernate会产生错误判断,又以为它们不是同一个对象,因此我们还得重写User

    的hashCode方法。如何重写hashCode方法呢?


    4、HashCode的重写。


    如第2节所讲,哈希码要完成这么一件事,首先要保证如果equlas出来的结果相等,那么hashCode也相等。

    像上面的u1和u2,由于名字都是“张三”,所以应该返回相同的hashCode。所以我们可以想一个办法。让User的哈希码返回User里面name字段的哈希码,这样就保证,名字相同的人,不但equlas方法相同,而且hashCode相等。


    那么User类就变成

    Java代码

    1. public class User{  
    2. private String userName;  
    3.   
    4. //覆盖Object里的equals方法  
    5. public boolean equals(Object arg0){  
    6. if(!(arg0 instanceof User)){  
    7. return false;  
    8.    }  
    9.   
    10.    User user = (User)arg0;  
    11.   
    12. //如果名字相同,则表示属于同一个对象。  
    13.   
    14. if(user.getName().equals(this.getName)){  
    15. return true;  
    16. else{  
    17. return false;  
    18.    }  
    19.    }



       //覆盖Object里的hashCode方法


    Java代码

      1. public int hashCode(){  
      2. return name.hashCode();//返回名字的哈希码。  
      3.  }


      这样可以保证hibernate根据我们自己的需求来判断重复对象