equals

equals()方法与==的区别

  • ==:对于基本类型比较的是值,对于引用类型比较的是地址
1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {

int a = 10;
int b = 10;
System.out.println(a == b);//true
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2);//true
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str3 == str4);//false
}

在这里解释一下String类型在jvm是怎样存储的

如果使用“”创建String类型,如str1,str2,它会去常量池查找有没有当前我要创建的值,如果有直接将常量池的引用复制给该变量。第一次使用String str1 = “hello”,由于常量池中没有“hello”,它会在常量池中创建,在使用String str2 = “hello”,由于常量池中存在”hello”,str2它会直接引用这个值,所以str1 == str2为true

使用new创建String对象的时候,它回到常量池去查找有没有我要创建的值,如果有则拷贝一份到堆中,将该副本的引用赋值给变量。如果没有,则实例化该对象放到常量池,并且拷贝副本到堆中,将副本的引用复制给变量

如:String str3 = new String(“hello”),常量池创建,拷贝一份到堆中,并副本赋值给str3,String str4 = new String(“hello”),从常量池拷贝一份到堆中,并将副本引用赋值给str4.所有str3 == str4为false

2

  • equals:Object中的方法,在Object中比较的也是两个对象的地址,但是一般情况下,都要重写equals方法,来指定相等的规则。比如String类,重写equsls方法,比较的是String的值,而不是地址。

案例:一个Student类,重写equals方法,如果它的name相等就认为他们是同一个学生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Student {

private String name;

private int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public boolean equals(Object obj) {
//两个对象的地址相等,一定是同一个对象
if(this==obj) {
return true;
}
if(obj instanceof Student) {
Student s = (Student) obj;
if(this.name.equals(s.name)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
Student s1 = new Student("zs", 18);
Student s2 = new Student("zs", 20);
System.out.println(s1.equals(s2));//true
System.out.println(s1 == s2);//false
}
}

eausle的特性

  1. 自反性:a.equals(a)一定为true
  2. 对称性: 如果a.equals(b)为true,那么b.equals(a)一定也为true
  3. 传递性: a.equals(b)为true,b.equals(c)为true,那么a.equals(c)也为true

equals与hashcode

重写equals是否需要重写hashcode?

在api中是建议在重写equals时,我们有必要重写hashcode.

在一些用到hashcode的数据结构存储数据的时候,如hashset,是一定要重写的hashcode的

hashset存放元素的时候存放的是不重复的元素,它存数据的时候会根据元素的hash值和equals方法来判断是否添加,如果两个元素的hash值相同和equals方法返回为true,则认为元素相同,hashset不将它添加进去。这样就会产生一个问题,假设有 student1 = new Student(“zs”,18),student2 = new Student(“zs”,18),hashset在添加这两个对象的时候,只会将一个对象添加进去,但是如果不重写hashcode,hastset会认为这是两个不同的元素并将它添加进去,当我们在从hashset中取出数据的时候会发现取出了两个相同对象,这与hashset的的规则不符合,所以重写equals方需要重写hashcode.

hashset添加元素的判断

1
2
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))

案例:一个Student类,重写equals,不重写hashcode,创建两个属性相等的对象,存放到hashset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public boolean equals(Object obj) {
//两个对象的地址相等,一定是同一个对象
if(this==obj) {
return true;
}
if(obj instanceof Student) {
Student s = (Student) obj;
if(this.name.equals(s.name)&&this.age == s.age) {
return true;
}
}
return false;
}

存放到hashset,并输出到控制台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {

Student s1 = new Student("zs", 18);
Student s2 = new Student("zs", 18);

HashSet<Student> set = new HashSet<>();
set.add(s1);
set.add(s2);
Iterator<Student> iterator = set.iterator();
while(iterator.hasNext()) {
Student next = iterator.next();
System.out.println(next);
}
}

输出结果

3

文章目录
  1. 1. equals()方法与==的区别
  2. 2. eausle的特性
  3. 3. equals与hashcode
|
载入天数...载入时分秒...