Fork me on GitHub
文章目录
  1. 1. 前言
  2. 2. 一个奇怪的问题
  3. 3. 感谢

前言


众所周知,HashSet中不含有重复的元素.本文用几个例子来加深对不重复的理解.

一个奇怪的问题


先来看一段代码,代码如下:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.yongf.algorithm;

import java.util.HashSet;

/**
* Created by yongf on 16-4-28.
*/

public class UnderstandingHashSet {

public static void main(String[] args) {
HashSet<Person> hs = new HashSet<>();
Person person = new Person("Scott Wang", 20);
hs.add(person);

person.setName("王用");
person.setAge(20);

hs.add(person);

System.out.println("hs = " + hs);
}
}

class Person {
private String name;
private int age;

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

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

运行结果为:

1
hs = [Person{name='王用', age=21}]

看到这里,你可能就疑问了,唉,怎么只有一个元素,不是add了两个元素么?一个是(“Scott Wang”, 20),一个是(“王用”, 20),这输出不对吧.

其实你这么分析,好像挺对,不过你忽视了一个东西,判断是否重复基于hashCode(),而在上述代码中,Person类根本就没有重写hashCode()方法,所以,HashSet在比较元素的时候根本就没有考虑name和age属性,因为继承的是Object类的hashCode()方法,所以只会比较对象,只要是同一个对象,在不重写hashCode()方法的情况下,都被认为是同一个对象.

好吧,那我们重写hashCode()方法,代码如下:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.yongf.algorithm;

import java.util.HashSet;

/**
* Created by yongf on 16-4-28.
*/

public class UnderstandingHashSet {

public static void main(String[] args) {
HashSet<Person> hs = new HashSet<>();
Person person = new Person("Scott Wang", 20);
hs.add(person);

person.setName("王用");
person.setAge(20);

hs.add(person);

System.out.println("hs = " + hs);
}
}

class Person {
private String name;
private int age;

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

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

@Override
public int hashCode() {
return name.hashCode() + age * 100;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

现在hashCode()方法与name,age属性挂钩上了,在此运行,结果如下:

1
hs = [Person{name='王用', age=20}, Person{name='王用', age=20}]

不过,这里的结果还是两个一样的,我的想法如下图所示:

我的理解,欢迎指正

不过,如果创建一个新的person1 = new Person(“Scott Wang”, 20),然后hs.add(person1),结果如下:

1
hs = [Person{name='Scott Wang', age=20}, Person{name='Scott Wang', age=20}]

这显然也是不符合我们预期的,如果name和age都一样,我们预期两者是不同的,为此,我们需要重写equals方法,因为HashSet的判重涉及到了hashCode(), equals()方法, 于是,经过我们的两次修正,最后的代码如下:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.yongf.algorithm;

import java.util.HashSet;

/**
* Created by yongf on 16-4-28.
*/

public class UnderstandingHashSet {

public static void main(String[] args) {
HashSet<Person> hs = new HashSet<>();
Person person = new Person("Scott Wang", 20);
hs.add(person);

Person person1 = new Person("Scott Wang", 20);

hs.add(person1);

hs.add(new Person("老码", 20));
hs.add(new Person("王用", 20));

System.out.println("hs = " + hs);
}
}

class Person {
private String name;
private int age;

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

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

@Override
public int hashCode() {
return name.hashCode() + age * 100;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person person = (Person) obj;
return person.name.equals(name) && (person.age == age);
} else {
return false;
}
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

最后的运行结果为:

1
hs = [Person{name='王用', age=20}, Person{name='Scott Wang', age=20}, Person{name='老码', age=20}]

OK,这个结果在预料之中.那么,我们下次再见 =_=

感谢

感谢访问我的个人博客的朋友,如果您感觉本站对您搜索的问题有所帮助,并感觉对本站还满意的话,顶一下吧,希望您把本站分享给您的朋友!在此对您表示由衷的谢意! :-)