我是靠谱客的博主 平淡大米,这篇文章主要介绍黑马程序员--07.集合框架--06.【HashSet】集合框架--6,现在分享给大家,希望可以做个参考。

集合框架--6

      HashSet

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

1.    HashSet

1). HashSet验证Set的无序性和唯一性

(1). HashSet验证无序性

示例代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1. 验证无序性 class HashDemoI { public static void sop(Object o){ System.out.println(o); } public static void main(String[] args){ HashSeths =new HashSet(); hs.add("java001"); hs.add("java002"); hs.add("java003"); hs.add("java004"); Iteratorit =hs.iterator(); while(it.hasNext()){ sop(it.next()); } } }

打印结果:

java04

java02

java03

java01

【结论】存入的时候,是java01~java04  取出的时候是java04、java02、java03、java01  存入时候的顺序和存储、取出的顺序不一致,所以通过HashSet可以检验Set是无序的。

(2). HashSet验证唯一性

[1]. 存入的对象是字符串 ----重复传入一个字符串对象

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//2. 验证唯一性 public class HashSetDemoII { public static void sop(Object o){ System.out.println(o); } public static void main(String[] args){ HashSeths =new HashSet(); sop("java001 really add? "+ hs.add("java001")); sop("java001 really add? "+ hs.add("java001")); sop("java002 really add? "+ hs.add("java002")); sop("java003 really add? "+ hs.add("java003")); sop("java003 really add? "+ hs.add("java003")); sop("最终元素集合中的内容..."); Iteratorit =hs.iterator(); while(it.hasNext()){ sop(it.next()); } } }
 

打印结果:


【结论】为什么Collectionadd方法返回值是boolean类型的?

这个boolean类型表示向集合中添加元素是否成功。不成功,add返回false;否则,返回true

 

【分析】运行完sop("java001 really add? "+ hs.add("java001"));之后,接着运行      sop("java001 really add? "+ hs.add("java001"));,向hs集合中添加相同的元素。此时hs的底层数据结构调用了String类的equals方法。由于String类的equals方法重写过,判定结果是这两个对象的内容一样,所以,没有将第二个"java001"添加到集合中。此时add方法返回false。

[2]. 存入的对象是自定义对象

{1}. 测试代码不变:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class HashSetDemoIII { public static void sop(Object o){ System.out.println(o); } public static void main(String[] args){ HashSeths =new HashSet(); hs.add(new Person("a1", 11)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 13)); hs.add(new Person("a2", 12)); Iteratorit =hs.iterator(); while(it.hasNext()){ sop(it.next()); } } }

{2}. 没有重写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
//2. 验证唯一性,存入自定义元素 class Person{ private String name; private int age; public static void sop(Object o){ System.out.println(o); } public Person(String name, int age){ this.name =name; this.age =age; } public void setName(String name){ this.name =name; } public String getName(){ return this.name; } public void setAge(int age){ this.age =age; } public int getAge(){ return this.age; } public String toString(){ return this.name+"::"+this.age; } }
 

测试结果:


【结论】循环迭代结果:a2::12打印了两次,说明重复的元素new Person("a2", 12)被添加到集合中去。没有保证HashSet的唯一性。

{3}. 为Person类重写equals()方法判定两个对象的内容是否一致

复制代码
1
2
3
4
5
6
7
8
9
10
11
public boolean equals(Object obj){ if(!(obj instanceof Person)){ return false; } Personp =(Person)obj; //用来查看equals方法是否被调用 sop(this.name +".......equals......."+ p.name); //认为名字相同并且年龄一样大的两个对象是一个 return this.name.equals(p.name) && this.age == p.age; }

测试结果:


【结论】循环迭代结果:a2::12打印了两次,说明重复的元素new Person("a2", 12)被添加到集合中去。没有保证HashSet的唯一性。

同时equals没有被调用,说明仅仅重写equals方法没起到作用

 

【分析】HashSet在存储元素的时候,是先查看两个对象的哈希值是否一样的。

{3}1.

如果哈希值一样再调用元素对象的equals方法,查看两个对象的内容是否一样。

{1}. 如果equlas比较的值一样,说明两个对象相同能添加到HashSet对应的集合中。

{2}. 如果equlas比较的值一样,说明两个对象可以添加到HashSet对应的集合中

 

{3}2.

       如果哈希值不一样,直接认为两个对象不一样,equals方法不起作用

【本例分析】这个例子中,由于四个Person类的对象都是new出来的,所以没有重写的hashCode是调用本地方法产生的值,所以一定是四个不相同的hashCode值。hashCode值都不一样,equals方法不起作用。

(3). 重写HashCode方法

为避免内容重复的数据添加到HashSet集合中,就必须重写hashCode()方法。

[1]. hashCode的返回值设置为统一的数值:

示例代码:

复制代码
1
2
3
4
public int hashCode(){ System.out.println(this.name +"...hashCode"); return 60; }

打印结果:


重复的元素没有被添加进来。

【建议】不要将hashCode的返回值都设置成一样的。因为hashCode的值和内存地址有关,这样设置不科学

[2]. 根据比较的条件重写HashCode方法

复制代码
1
2
3
4
public int hashCode(){ sop(this.name +"......hashCode"); return this.name.hashCode() + 29*age; }

这种做法,同样可以避免HashSet集合中不会存入相同元素。

【两种方式的具体区别和详细过程见个人总结。】

(4). 重写hashCode和equals的时候,常犯的错误

[1]. 子类重写hashCode的时候,将方法名写错,写成hasCode

[2]. 子类重写equals的时候,将参数传错,本来应该是public boolean equals(Object obj){}却写成了public boolean equals(自定义类型自定义类型引用)。这样集合框架的底层不会调用这个重载的方法。

2.    HashSet总结

1). HashCode如何保证元素唯一性?

(1). 需要重写的方法

通过重写自定义类hashCode()equals( )两个方法来达到元素的唯一性保证。

(2). 方法重写之后,执行的顺序

[1]. 如果元素hashCode相同,才会使用equals()方法进行判断。

[2]. 如果元素hashCode不同不会调用equals()方法

2). 开发中的建议

(1). 自定义对象,一定要重写hashCode和equals两个方法

       如果不重写,则默认的本地方法hashCode【OS来产生】会产生值都不一样的hashCode,即使内容重复的元素会被添加到HashSet中,无法保证元素的唯一性

【注意】开发中重写这两个方法,方便集合框架的底层调用这些方法。

(2). 建立高效的hashCode会使得hashSet添加元素的过程更为高效。

       hashCode的值不同,则调用equals()方法比较的环节便可以省去。

3). HashSet判断和删除元素的依据

示例代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class HashSetDemoIV { public static void main(String[] args) { HashSeths =new HashSet(); hs.add(new Person("a1", 11)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 13)); System.out.println("hashSet中的元素:"+ hs); System.out.println("************************"); System.out.println("HashSet的 contains依据:"+ hs.contains(new Person("a1", 11))); System.out.println("************************"); System.out.println("HashSet的 remove依据:"+ hs.remove(new Person("a3", 13))); System.out.println("************************"); System.out.println("hashSet中的元素:"+ hs); } }

打印结果:

可以看出,hashSet在删除和判断元素的时候,依据的仍然是hashCode和equals这两个方法。

结论:

[1]. HashSet判断删除添加元素等操作依据的是被操作元素所在的类的hashCode()equals( )这两个方法。

[2]. ArrayList做同等的操作,依据的仅仅是equals( )方法

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

 

最后

以上就是平淡大米最近收集整理的关于黑马程序员--07.集合框架--06.【HashSet】集合框架--6的全部内容,更多相关黑马程序员--07内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(86)

评论列表共有 0 条评论

立即
投稿
返回
顶部