equals和==
==操作符:
java的数据类型可以分为两种:
1.基本数据类型
- byte(8位)、short(16位)、int(32位)、long(64位)、double(64位)、boolean、float(32位)、char(16位)---一个字节占8位
- boolean特殊一点,1.JVM没有提供booolean类型专用的字节码指令,而是使用int相关指令来代替。2.对boolean数组的访问与修改,会共用byte数组的baload和bastore指令。
基本数据类型使用==就是比较他们的值是否相同
2.引用类型
==比较的是他们在内存中存放的地址,所以除非是同一个对象,否则就会返回false
对象是存放在堆上的,栈中存放的是对象的引用,“==”比较的是栈中的值,如果要比较堆中对象的内容是否相同,就需要重写equals方法
equals方法:
默认情况下(没有重写equals),equals比较的是对象的内存地址是否指向同一个地址,object对象默认的equsal方法等同于==
public boolean equals(Object obj) {
return (this == obj);
}
如果重写了equals方法,就需要根据对象的内容是否相等来判断了
//String类的equals方法
public boolean equals(Object anObject) {
//地址相同 返回true
if (this == anObject) {
return true;
}
//判断类型是否为String,否则返回false
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = length();
//判断长度是否相同
if (n == anotherString.length()) {
int i = 0;
//逐个字符进行比对
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}
TextUtils工具类中的equals方法
public static boolean equals(CharSequence a, CharSequence b) {
//判断内存地址
if (a == b) return true;
int length;
//判断空值和长度
if (a != null && b != null && (length = a.length()) == b.length()) {
//如果是String类型 调用String的equals方法
if (a instanceof String && b instanceof String) {
return a.equals(b);
} else {
//遍历字符进行比对
for (int i = 0; i < length; i++) {
if (a.charAt(i) != b.charAt(i)) return false;
}
return true;
}
}
return false;
}
对比两种重写equals方法,可以发现,首先要对比的是“==”内存地址,其次判断对象是否为空以及类型是否一致,最后再根据具体条件进行比对
equals方法有几个特性需要关注一下
- 自反性:a.equals(a) 返回true
- 对称性:a.equals(b)返回ture那么b.equals(a)也返回true
- 传递性:a.equals(b) b.equals(c) 那么 a.equals(c)成立
- 一致性:如果参与比较的对象没有任何改变,那么比较的结果也不应改变
- 非空性:任何非空的对象A A.equals(null)返回false
hashcode
1、hash和hash表是什么?
hash是一个函数,该函数中的实现就是一种算法,就是通过一系列的算法来得到一个hash值。这个时候,我们就需要知道另一个东西,hash表,通过hash算法得到的hash值就在这张hash表中,也就是说,hash表就是所有的hash值组成的,有很多种hash函数,也就代表着有很多种算法得到hash值。
2、hashcode
hashcode就是通过hash函数得来的,通俗的说,就是通过某一种算法得到的,hashcode就是在hash表中有对应的位置。
每个对象都有hashcode,对象的hashcode怎么得来的呢?
首先一个对象肯定有物理地址,在别的博文中会hashcode说成是代表对象的地址,这里肯定会让读者形成误区,对象的物理地址跟这个hashcode地址不一样,hashcode代表对象的地址说的是对象在hash表中的位置,物理地址说的对象存放在内存中的地址,那么对象如何得到hashcode呢?
通过对象的内部地址(也就是物理地址)转换成一个整数,然后该整数通过hash函数的算法就得到了hashcode。所以,hashcode是什么呢?就是在hash表中对应的位置。
这里如果还不是很清楚的话,举个例子,hash表中有 hashcode为1、hashcode为2、(…)3、4、5、6、7、8这样八个位置,有一个对象A,A的物理地址转换为一个整数17(这是假如),就通过直接取余算法,17%8=1,那么A的hashcode就为1,且A就在hash表中1的位置。
3、equals方法和hashcode的关系?
- 1、如果两个对象equals相等,那么这两个对象的HashCode一定也相同
- 2、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置
4、为什么equals方法重写的话,建议也一起重写hashcode方法?
class A {
private String name;
private int age;
//重写equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof A)) return false;
A a = (A) o;
return age == a.age &&
Objects.equals(name, a.name);
}
//重写hashCode
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
在重写了equals方法后,尽量也重写了hashcode方法,通过一定的算法,使他们在equals相等时,也会有相同的hashcode值。