java 字符串,hashCode

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 字符串,hashCode相关的知识,希望对你有一定的参考价值。

public class Test
public static void main(String[] args)
String a="abc";
String b=new String("abc");
System.out.println(a==b);
System.out.println(a.hashCode()==b.hashCode());


输出:
false
true
为嘛,a和b不是在内存中有两个字符串,他们的物理地址不一样吧?
第二个输出true的原因是什么?
hashCode 返回值是根据字符串内容么?

String类型在内存堆中存在一个静态池,String a = “abc”,那么这个是在静态池里取出来的,而b=new String(“abc”)是new一个新的对象,那么在内存堆中会开辟新的空间的;
a==b实际是比较的其引用地址的,因为是指向不同的地址,所以a==b当然是false;
而a.hashcode()==b.hashcode()实际就等同于a.equals(b);实际比较是其内容,跟引用没有关系的!
因为equals和hashcode我们重写的时候都会保持一致的!追问

自己构造实体类的时候一般如何复写hashCode?
比如学生仅有姓名年龄两个属性,如果两个属性相等判断为同一个实例,
这样的话我可以写么:
public int hashCode()

return 1;

不过hashCode和equals方法重新保持一致貌似也很不错的。。。。。

追答

一般如果使用IDE来开发的,都可以自动生成重写的equals和hashcode方法的!

参考技术A a指向字符串常量池,因为“abc”是存在字符串常量池中。
b指向堆,因为创建的对象在堆中。
所以,a==b,肯定返回false

hashcode是把你的值(a是“abc”,b也是“abc”),根据一套算法算出来的,算法是固定不变的,传入的值一样,hascode肯定一样。
所以,a的hashcode值与hashcode值,返回true
参考技术B a,b的物理地址是不一样的,
对象是否相等的规则
1 判断两个对象的hashCode是否相等; 如果不相等,认为两个对象也不相等, 完毕.
2 如果相等, 再调用equals方法.

Java中hashcode的计算方式

Java中hashcode的计算方式

String计算hashCode的方式

/**
  * hashcode的计算方式为,以31为权重,举例“java”字符串的计算
  * j 的 ASCII码 为 106
  * a 的 ASCII码 为 97
  * v 的 ASCII码 为 118
  * 字符串 va 的 hashcode为 118 * 31 + 97
  * 字符串 java 的 hashcode为 106 * 31 * 31 * 31  + 97 * 31 * 31 + 118 * 31 + 97
*/
System.out.println(Integer.valueOf('j')); //ASCII码:106
System.out.println(Integer.valueOf('a')); //ASCII码:97
System.out.println(Integer.valueOf('v')); //ASCII码:118
System.out.println(Integer.valueOf('a')); //ASCII码:97
int hashcode = 106 * 31 * 31 * 31  + 97 * 31 * 31 + 118 * 31 + 97;
System.out.println("hashCode计算的值:" + hashcode);   //3254818
System.out.println("Objects hashCode:" + Objects.hashCode("java") ); //3254818
System.out.println("String hashCode:" + "java".hashCode()); //3254818
//Objects.hash在上面的计算方式基础上额外增加了31
System.out.println("Objects hash:" + (3254818 + 31));  //3254849
System.out.println("Objects hash:" + Objects.hash("java") ); //3254849

Objects.hash实际上是由Arrays.hashCode(values)运算得出的,计算过程如下:

hashcode有什么用?
    当过多对象进行比较时,需要调用n次equals逐个进行比较,会大大降低效率
    但是不同的对象可能会生成相同的hashcode值,所以不能根据hashcode值判断两个对象是否相等,但是可以直接根据hashcode值判断两个对象不等
    如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。

Entity重写hashCode方法

  • 为什么要重写equals方法?
    如果不重写entity的equals方法,默认调用equals,比较的结果并不准确。
public class Users 
    private int id;
    private String name;

    public Users(int id,String name)
        this.id = id;
        this.name = name;
    

    public static void main(String[] args) 
        Users user1 = new Users(1,"小妖");
        Users user2 = new Users(1,"小妖");
        System.out.println(user1.equals(user2)); //打印结果:false
    

在没有重写equals的情况下,默认调用的是Object的equals,和使用“==”比较的结果一样

  • 对于值对象,==比较的是两个对象的值
  • 对于引用对象,==比较的是两个对象的地址
public boolean equals(Object obj) 
   return (this == obj);

而重写equals方法之后,可以根据entity本身的属性来判断,该实体类是否相等

public class Users 
    private int id;
    private String name;

    public Users(int id,String name)
        this.id = id;
        this.name = name;
    

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Users users = (Users) o;
        return id == users.id &&
                Objects.equals(name, users.name);
    

	@Override
    public int hashCode() 
        return Objects.hash(id, name);
    
  
    public static void main(String[] args) 
        Users user1 = new Users(1,"小妖");
        Users user2 = new Users(1,"小妖");
        System.out.println(user1.equals(user2)); //打印结果:true
    

  • 为什么要重写hashCode方法?
    重写equal方法时,一定要重写hashCode方法!保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。
    如果不重写hashCode方法,调用的是Object中的hashCode方法
public native int hashCode();

重写后的hashcode方法会基于entity的属性计算值

	@Override
    public int hashCode() 
        return Objects.hash(id, name);
    

Entity的hashcode方法主要用于将entity放入HashMap、HashSet等集合框架中。
    两个对象相等,hashcode一定相等
    两个对象不等,hashcode不一定不等
    hashcode相等,两个对象不一定相等
    hashcode不等,两个对象一定不等

HashMap中计算hashCode的应用

  • hashMap中hashCode的计算
  • hashMap的大致存取过程

put操作:
    当调用put(key,value)方法的时候,会先对键key调用key.hashcode()方法,根据方法返回的hashcode来找到bucket的位置来存Entry对象。
    根据hashcode找到对应的bucket之后,通过equals()方法在对应的链表逐一对比,检查这个链表里有没存在相同的key对象。如果有,则用新的value取代旧的value。如果没有,在链表的尾部加上这个新的Entry对象。

get操作:
    当调用get(key)的时候,会调用key的hashcode方法获得hashcode。根据hashcode获取相应的bucket。
    由于一个bucket对应的链表中可能存有多个Entry,这个时候会调用key的equals方法来找到对应的Entry

以上是关于java 字符串,hashCode的主要内容,如果未能解决你的问题,请参考以下文章

Java中hashcode的计算方式

Java中hashcode的计算方式

Java中hashcode的计算方式

Java中hashcode的计算方式

Java HashCode

java 17- 3 hashCode()方法