String的equals以及hashcode比较总结

摘要

equals()方法,首先是Object类中被定义的,它的定义中就是使用“==”方式来匹配的。如果不重新equals()方法,且其父类也不重写equals()方法,则默认equals()操作就是对比

关于“==”

 

Java中当“==”匹配时,其实就是比较两个内存单元的内容是否一样。

如果是原始类型如byte、short、boolean、int等,就是直接比较它们的值,这个大家应该都懂。

如果是引用,比较的就是引用的值。即比较两个对象的地址是否一样,换句话说,如果两个引用所保存的对象是同一对象,则认为它们相等,否则返回false。

 

Mypsd_13889_201102171810270013B.jpg

关于equals()

 

  equals()方法,首先是Object类中被定义的,它的定义中就是使用“==”方式来匹配的。如果不重新equals()方法,且其父类也不重写equals()方法,则默认equals()操作就是对比对象的地址。String有点特殊,它本身就实现了equals()方法。

 

迷惑:equals()重写之后,一般会重写hashCode()方法吗?

 

   首先我们要知道,Java中的hashCode是什么? hashCode()方法提供了对象的hashCode值,它与equals()一样在Object类中提供,不过它是一个native(本地)方法。通常情况下,这个值是对象头部的一部分二进制位组成的数字,这个对象具有一定的标识对象的意义存在,但绝不等价于地址。

   hashCode的作用--它为了产生一个可以标识对象的数字,不管多么复杂的对象都可以用一个数字来标识。为什么需要数字来标识呢? 因为这有利于快速查找。

hashCode只能说是标识对象,因此在Hash算法中可以将对象相对离散开,这样可以在查找数据的时候根据这个key快速的缩小数据范围。但不能说hashCode值一定是唯一的,所以在Hash算法中定位到具体的链表后,需要进一步循环链表,任何通过equals方法来对比Key的值是否一样。这时候hashCode和equalse似乎就成了天生的一对。

   总结:它们一个是为了算法快速定位数据而存在的,一个是为了对比真实值而存在的。可以说hashCode与两个对象是否一致一点关系都没有。

   换个角度来讲,如果两个对象(不是String)之间判定出来hashCode不一样,也不能说它们的值不一样,有可能equalse()匹配的是一个综合值,与hashCode一点关系没有。至于equals()内部要怎么去对比,可以自己根据实际情况去优化。

 

编译时优化方案:能提前做的事情就提前做

 

Java代码  收藏代码

  1. String a = "a"+"b"+1;  

  2. String b = "ab1";  

  3. System.out.println(a==b);    

       答案:true

       在a中,因为都是常量,编译时期就能确定,所以在编译时,就将a编译成"ab1"。

       编译器优化一定是在编译阶段能确定优化后不会影响整体功能,类似于final引用,这个引用只能赋值一次,但无法确定赋值的内容是什么。只有编译阶段能确定赋值的内容,编译器才能进行编译时优化。

       在编译阶段能确定的内容只能来自于常量池中,例如String、long、int等常量,当然不包括new String();new Integer();这样的操作,因为这是运行时决定的,也不包括返回值、变量等。因为不确定。

    如:

Java代码  收藏代码

  1. String a = "a";  

  2. String b = a + "b";  

  3. String c = "ab";  

  4. System.out.println(a==c);    

    答案:false

 

事情没绝对,还得看场景

 

       有人认为StringBuilder.append()比String "+" 要快。其实String "+" 内部也是进行StringBuilder.append()操作, 它本身是不慢的,而是大循环中大量的内存使用,使得它的内存开销变大,导致了系统频繁GC,而且是更多的FULL GC,效率才会急剧下降。 如果是编译时就能确定的值,String "+" 还是要更快的。


IT家园
IT家园

网友最新评论 (0)