zoukankan      html  css  js  c++  java
  • java中的“==”,equals()和hashcde的区别

    1、 ==

    java中的数据类型,可分为两类:

     1、基本数据类型,也称原始数据类型

      byte,short,char,int,long,float,double,boolean 他们 之间的比较,应用(==),比较的是他们的值。

        2、引用类型(类i,接口,数组)

      当他们用(==)进行比较的时候,比较的 是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的记过位true,否则比较后结果为false。

      对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见“==”是对栈 中的值进行比较的。如果要比较堆中对象的内容是否想用,那么就要充血equals方法了。

     1 public static void main(String[] args){
     2     int int1=12;
     3     int int2=12;
     4     Integer Integer1 = new integer(12);
     5     Integer Integer2 =new Integer(12);
     6     Integer Integer3  = new Integer(12);
     7     Integer a1 =127 8     Integer b1 = 127 9     Integer  a  =12810     Integer   b=12811     String s1 = "str";
    12     String  s2 = "str";
    13     String str1 =new String(“str”);
    14     String str2 =new String(“str”)
    15 
    16      System.out,println(“int1==int2”+(int1==int2));
    17      System.out,println("int1==integer1+"(int1==integer1));
    18      System.out,println("Integer1==Integer2"+(Integer1==Integer2));
    19      System.out,println("Integer3==b1"+(Integer3==b1));
    20      System.out,println("a1==b1"+(a1==b1));
    21      System.out,println("a=b"+(a==b));
    22      System.out,println("s1==s2"+(s1==s2));
    23      System.out,println("s1==str1"+()s1==str1);
    24      System.out,println("str1==str2"+(str1==str2));
    25  }                       

    输出结果:

    int1==int2  true

    int1==Integer1;true//Innteger会自动拆箱为int,所以true;(当Integer与int进行==比较是,Integer会拆箱成一个int类型,所以还是相当于两个int型比较,这里的Integer,不管是直接赋值,还是new创建的对象,质押跟int比较就会拆箱为int类型,所以是相等的)

    Integer1==Integer2;  false//是不同的对象,在内存中的存放地址不同(这是两个对象类型,而且不会进行拆箱比较),所以为false

    Integer3==b1;  false//integer3是一个对象类型,而b1是一个常量他们存放内存的位置不一样,素以也不等.

    a1==b1;   //true

    a==b;   //false      这是因为Integer作为常量是,对于-128到127之间的数,会进行缓存,也即是说int a1=127时,在 范围之内,这个时候就存放在缓存中,挡再创建a时,java发现缓存中存在127这个数了,就直接取出来赋值给a,所以a1==b1.当超过范围就是 new integer()来new一个对象了,所以a,b都是new Integer(128)出来的变量,所以他们不等 .

    s1==s2;  true//java中唯一不需要new'既可以产生对象的途径 ,这种形式的赋值称为直接量,他被存放在一个叫字符串拘留池(常量池)的地方;而new创建的对象都放在堆上.

    (什么是字符串拘留?当我们声明一个字符串String s="hello"时,JVM会先从常量池中查找又没哟值为"Hello"的对象,如果有,会把该对象赋给当前引用,也就是说原来的引用和现在的引用指向同一个对象;如果没有,则在拘留池中创建一个值为"Hello"的对象,如果下一次还有类似的语句,例如String str="Hello"时,又会指向"Hello"这个对象,以这种形式声明字符串,无论有多少个都指向同一个底线)

    s1==str1;false//    以new这种形式创建的对象,每执行一次就生成一个新对象,是两个独立对象

    str1==str2;false//

    2、要是类中覆盖了equals方法,那么就u要根据具体的代码来是却抵inequals方法的作用了,覆盖后一般都是通过对象的内容是否想等来判断对象是否想等。下面对equals进行重写。

     1 public boolean equals(Object anObject){
     2      if (this==anObject){
     3          return true;
     4 }
     5     if(anObject insrtanceof Striing){//instancef操纵检查符
     6         String anotherString = (String)anObject;
     7         int n = cont;
     8         if(n==anotherString.count){
     9         char  v1[] = values;
    10         char  v2[]=anotherString.value;
    11         int i  = offset;
    12         int j = anotherString.value;
    13         while (n--!=0){
    14               f(v1[I++]!=v2[j++])
    15               return false;
    16 }
    17         return  true;}
    18 } 
    19
    20 retrn false; 

    }

    即String中equals方法判断相等的步骤是:

    1、若A==B即是同一个String对象,返回true;

    2、若对比对象是String类型则继续,否则返回ufalse;

    3、判断A、B长的是否一样,不一样的话返回false

    4、逐个字符比较,若有不相等字符,返回false

    这里对equals需要注意我五点:

    1、自反性:对人一引用值x,x.equals(x)的返回值一定为true;

    2、对称性:对于任何引用值x,y当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值应为true;

    3、传递性:如果.x.equals(y)=true,y.equals(z)=true,则x.equals(z)=true

    4、一致性:若参与比较的对象没有任何改变,则对象比较的结果哦也不应有任何改变

    5、非空性:任何非空的引用值x,x.equals(null)的返回值一定为false;

    实现高质量equals方法的诀窍:

    1、使用==符号检查“参数是否为这个对象的引用“。如果是,则返回true。这只不过是一种性能优化,如果比价操作有可能很昂贵,就值得 这么做。

    2、使用instancef操作符检查”参数是否为正确的类型“。如果不是,则返回false。一般来说,所谓”正确的类型“是指equals方法所在的那个类。

    3、把参数转换陈正确的类型。因为转换之前进行过instanceof测试,素偶一确保会成功。

    4、对于该类中的每个”关键“域,检查参数中的域是否与该对象中对应的域相匹配。如果 这些 测试全部成功,则返回true,否则false;

    5、当编写完成了equals方法之后,检查”对称性“,”传递性“,”一致性“。

    3、hashCode

    hashCode()方法返回的就是一个数值,生成一个hash码,主要用途就是对对象进行散列的时候作为key输入,hashCode方法实际上返回的就是对象存储的屋里地址(实际上并不是真正的内存的物理地址)

    散列函数,散列算法,哈希函数是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数将任意长度的二进制值映射位较短的固定长度的二进制值,这个小的二进制值称为哈希值,好的散列函数在啊输入域中很少出现散列冲突。

    所有散列函数都有如下一个基本特征:

    1:如果a=b,则h(a)=h(b)。

    2:如果a!=b,则h(a)与h(b)可能得到相同 的三列支散列值。

    hashCode的作用:Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者无序,但元素不可重复。

    要想保证袁术不重复,可拉ing个是否重复应该依据什么来判断,可以使用Object。equals方法,但是当元素很多的时候,后添加到集合中的元素比较的次数就非常多来,也就是说,如果集合中现在已经有2000个元素,那么第2001个元素加入集合是,他就要调用2000次equals方法,这显然会大大降低效率,所以Java采用来哈希表的原理。如此一来先吊用这个元素的hashCode方法,就一下子能定位倒他应该放置的屋里位置上;如果这个位置上没有元素,就直接存储在这个位置上,不用再进行任何比较;如果这个位置上已经有元素来,就调用它的equals方法与新元素进行比较,相同的话就不存,不相同就散列其他的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低来,几乎只需要一两次。

    4、equals方法和hashCode方法关系

    Java对于equals放大和hashCode方法是这样规定的:

    (1)同一对象上对此调用hashCode()方法,总是返回相同的整型值。

    (2)如果a.equals(b),则一定有a.hashCode()一定等于b.hashCode()。

    (3)如果!a.equals(b),则a.hashCode()不一定等于b.hashCode()。此时如果a.hashCode()总是不等于b.hashCode(),会提高hashtables的性能。

    (4)a.hashCode()==b.hahsCode(),则a.equals(b)可真可假。

    (5)a.hashCode()!=b.hashCode(),则a.equals(b)为假

    结论:

    1、如果两个对象equals,java运行时环境会认为他们的hashCode一定想等。

    2、如果两个对象不equals,他们的hashCode有可能想等。

    3、如果两个对象hashCode想等,他们不一定equals。

    4、如果两个对象hashCode不想等,他们一定不equals。

     关于这两个方法的重要规范

    规范一:若要重写equals(Object obj)方法,有必要重写hashCode()方法,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashCode()返回值,简单来说“如果两个对象相同,那么他们的hashCOde应该想等”。不过应该注意:这个只上规范,如果你非要写一个类让equals(Object obj)返回true而hashCode()返回两个不想等的值,编译和运行都是不会报错的,不过这样违反了Java规范,程序也就埋下了BUG

    规范二:如果equals(Object obj)返回false,既两个对象”不相同“,并不要求对这两个对象调用hashCode()方法得到阿玲个不相同的数,也就是”如果两个对象不相同,他的hashCode可能相同“。

    5、 总结:

      1、equal方法用于比较对象的内容是否想等(覆盖以后)

      2、hashCode方法只有在集合中用到

      3、当覆盖了equals方法时,比较对象是否想等将通过覆盖后的equals方法进行比较(判断对象的内容是否想等)。

      4、将对象放入到集合中是,首先判断要放入对象的hashCode值与集合中任意一个元素的hashCode值是否想等,如果不想等直接将该对象放入集合中,如果hashCode值想等,然后再通过equals方法判断equals方法判断要入对象与集合中的任意一个对象是否想等,如果equals判断不想等,直接将该元素放入到集合中,否则不放入。

  • 相关阅读:
    Django登录逻辑,中间用到Cookie创建、读取、删除、等操作
    CBV和FBV用户认证装饰器
    Django Session配置
    Django基于Cookie装饰器实现用户认证
    回归博客
    Jenkins部署
    iostat命令详解
    被入侵和删除木马程序的经历
    centos7 centos-home 磁盘转移至centos-root下
    zabbix图形显示口口不显示汉字
  • 原文地址:https://www.cnblogs.com/p-t-m/p/12694868.html
Copyright © 2011-2022 走看看