==和equals的区别
大白话回答
== 的作用:
基本类型:比较的就是值是否相同
引用类型:比较的就是地址值是否相同
equals 的作用:
引用类型:默认情况下,比较的是地址值。
注:不过,我们可以根据情况自己重写该方法。一般重写都是自动生成,比较对象的成员变量值是否相同
java中其实只有 == 比较,没有equals比较,其实底层还是 ==。只不过equals是很多类定义个方法而已,而这个方法把内存地址的比较改成基础数据类型的比较。就算String ,Integer,Long 等都回归到基础数据类型的比较。
详细描述如下
java中的数据类型,可分为两类:
基本数据类型,也称原始数据类型
byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。
在基础数据类型,就是字面值的比较,和数据类型无关,只要相同就是true
在封装数据类型中,它内存地址比较。在java中Short,Integer,Long都Byte范围的长度进来缓存,只要在-128-127都是相等的,其他的都是内存地址比较都是false
引用类型(类、接口、数组)
public class testDay {public static void main(String[] args) {String s1 = new String("11");String s2 = new String("11");System.out.println(s1 == s2);System.out.println(s1.equals(s2));}
}
结果是:false true
s1和s2都分别存储的是相应对象的地址。所以如果用 s1== s2时,比较的是两个对象的地址值(即比较引用是否相同),为false。而调用equals方向的时候比较的是相应地址里面的值,所以值为true。这里就需要详细描述下equals()了。
equals()方法详解
equals()方法是用来判断其他的对象是否和该对象相等。其再Object里面就有定义,所以任何一个对象都有equals()方法。区别在于是否重写了该方法。
先看下源码:
public boolean equals(Object obj) {return (this == obj);
}
很明显Object定义的是对两个对象的地址值进行的比较(即比较引用是否相同)。但是为什么String里面调用equals()却是比较的不是地址而是堆内存地址里面的值呢。这里就是个重点了,像String 、Math、Integer、Double等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。看下String里面重写的equals():
public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}
重写了之后就是这是进行的内容比较,而已经不再是之前地址的比较。依次类推Math、Integer、Double等这些类都是重写了equals()方法的,从而都会回归到基础数据类型的字面值比较
需要注意的是当equals()方法被override时,hashCode()也要被override。按照一般hashCode()方法的实现来说,相等的对象,它们的hashcode一定相等。为什么会这样,这里又要简单提一下hashcode了。
- 两个对象的 hashCode() 相同, 那么 equals() 也一定为 true吗?
不对,两个对象的 hashCode() 相同,equals() 不一定 true。
String str1 = "keep";
String str2 = "brother";
System. out. println(String. format("str1:%d | str2:%d", str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));
执行结果:
str1:1179395 | str2:1179395
false
代码解读:很显然“keep”和“brother”的 hashCode() 相同,然而 equals() 则为 false,因为在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。
- hashcode()浅谈
Hashcode覆盖的作用其实:未来这个对象要添加到java中数据结构比如:链表,map中,这个时候提供的数字。比如
明明是java中和equals和hashCode的区别问题,怎么一下子又扯到hashcode()上面去了。你肯定很郁闷,好了,我打个简单的例子你就知道为什么或者equals的时候会涉及到hashCode。
举例说明下:如果你想查找一个集合中是否包含某个对象,那么程序应该怎么写呢?不要用indexOf方法的话,就是从集合中去遍历然后比较是否想到。万一集合中有10000个元素呢,累屎了是吧。所以为了提高效率,哈希算法也就产生了。核心思想就是将集合分成若干个存储区域(可以看成一个个桶),每个对象可以计算出一个哈希码,可以根据哈希码分组,每组分别对应某个存储区域,这样一个对象根据它的哈希码就可以分到不同的存储区域(不同的区域)。
所以再比较元素的时候,实际上是先比较hashcode,如果相等了之后才去比较equal方法。
一个对象一般有key和value,可以根据key来计算它的hashCode值,再根据其hashCode值存储在不同的存储区域中,如上图。不同区域能存储多个值是因为会涉及到hash冲突的问题。简单如果两个不同对象的hashCode相同,这种现象称为hash冲突。简单来说就是hashCode相同但是equals不同的值。对于比较10000个元素就不需要遍历整个集合了,只需要计算要查找对象的key的hashCode,然后找到该hashCode对应的存储区域查找就over了。
大概可以知道,先通过hashcode来比较,如果hashcode相等,那么就用equals方法来比较两个对象是否相等。再重写了equals最好把hashCode也重写。其实这是一条规范,如果不这样做程序也可以执行,只不过会隐藏bug。一般一个类的对象如果会存储在HashTable,HashSet,HashMap等散列存储结构中,那么重写equals后最好也重写hashCode。