Java语言之集合框架Set
白羽 2018-07-09 来源 :网络 阅读 668 评论 0

摘要:本文将带你了解Java语言之集合框架Set,希望本文对大家学JAVA有所帮助。

 



 

集合框架 Set的特点:无序,不可以重复元素。

 

(1)HashSet:数据结构是哈希表。线程是非同步的。
              保证元素唯一性的原理:判断元素的hashCode值是否相同。
              如果相同,还会继续判断元素的equals方法,是否为true。


(2)TreeSet:可以对Set集合中的元素进行排序。
               底层数据结构是二叉树。
               保证元素唯一性的依据:compareTo方法return 0。

一、HashSet相关知识

    HashSet中的元素不可以重复,如果重复添加,则只会显示一个。

原理如下:

HashSet:底层数据结构是哈希表。是线程不安全的。不同步。

 

HashSet是如何保证元素唯一性的呢?
答:是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。

*******对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法**********

 

代码1:

[java] view plain copy
1. package com.package2;  
2.   
3. import java.util.*;  
4.   
5. public class HashSet222   
6. {  
7.   
8.     public static void main(String[] args)   
9.     {  
10.           
11.         HashSet hs = new HashSet();  
12.   
13.         hs.add("java01");  
14.         hs.add("java01");  
15.         hs.add("java02");  
16.         hs.add("java03");  
17.         hs.add("java03");  
18.         hs.add("java04");  
19.   
20.         Iterator it = hs.iterator();  
21.   
22.         while(it.hasNext())  
23.         {  
24.             System.out.println(it.next());  
25.         }  
26.     }  
27. }  
此demo将String类型的字符串添加进去,并且没有重复,结果如下:
java04java02java03java01
由此我们可以断定,String类已经实现了hashcode()方法和equals()方法。打开,帮助文档,确实(这不是废话么^_^)
但是,如果我们要将自定义的元素add进HashSet中,则必须定义其自己的hashcode()方法和equals()方法。如下所示:
代码2:
[java] view plain copy
1. package com.package2;  
2. import java.util.*;  
3. public class HashSet3   
4. {  
5.     public static void main(String[] args)   
6.     {  
7.         HashSet hs = new HashSet();  
8.   
9.         hs.add(new Person("a1",11));  
10.         hs.add(new Person("a2",12));  
11.         hs.add(new Person("a3",13));  
12.         hs.add(new Person("a2",12));  
13.         hs.add(new Person("a4",14));  
14.           
15.   
16.         Iterator it = hs.iterator();  
17.   
18.         while(it.hasNext())  
19.         {  
20.             Person p = (Person)it.next();  
21.             System.out.println(p.getName()+"::"+p.getAge());  
22.         }  
23.     }  
24. }  
25. class Person  
26. {  
27.     private String name;  
28.     private int age;  
29.     Person(String name,int age)  
30.     {  
31.         this.name = name;  
32.         this.age = age;  
33.     }  
34.       
35.     public int hashCode()  
36.     {  
37.         System.out.println(this.name+"....hashCode");  
38.         return name.hashCode()+age*37;  //保证此元素的返回值尽量不一致。  
39.     }  
40.   
41.     public boolean equals(Object obj)  
42.     {  
43.   
44.         if(!(obj instanceof Person))  
45.             return false;  
46.   
47.         Person p = (Person)obj;  
48.         System.out.println(this.name+"...equals.."+p.name);  
49.   
50.         return this.name.equals(p.name) && this.age == p.age;  
51.     }  
52.   
53.       
54.     public String getName()  
55.     {  
56.         return name;  
57.     }  
58.     public int getAge()  
59.     {  
60.         return age;  
61.     }  
62. }  
输出结果如下:
a1....hashCodea2....hashCodea3....hashCodea2....hashCodea2...equals..a2a4....hashCodea1::11a3::13a2::12a4::14
由此可以看出,将元素add时,会首先调用元素的hashcode()方法,当返回值重复时,会调用其equals方法。缺少任何一种方法都构不成一个HashSet集合。
 
 
二、TreeSet相关知识
TreeSet有俩种排序方式。
TreeSet排序的第一种方式:让元素自身具备比较性。步骤:将add进TreeSet中的元素实现Comparable接口,并且覆盖compareTo方法。这种顺序也是元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性(即利用其另一种构造函数建立对象)。在集合初始化时,就有了比较方式。
步骤:利用某个指定类实现Comparator接口,并且覆盖compare()方法,则此类会成为一个具备比较方法的类。在建立TreeSet的时候,将此类对象传入其中。
则此时,添加进TreeSet中的元素可按照指定比较方法进行排序。
 
下边举例演示俩种排序方式。
排序方式一:代码1:
[java] view plain copy
1. package com.package1;  
2.   
3. import java.util.*;  
4.   
5. public class TreeSettest {  
6.   
7.     public static void main(String[] args) {  
8.         //创建对象  
9.         TreeSet ts=new TreeSet();  
10.           
11.         //添加元素  
12.         ts.add("abcjjj");  
13.         ts.add("abb");  
14.         ts.add("daccc");  
15.         ts.add("gfg");  
16.         ts.add("geee");  
17.         ts.add("r");  
18.           
19.         //进行迭代  
20.         Iterator it=ts.iterator();  
21.           
22.         //循环取出元素  
23.         while(it.hasNext())  
24.         {  
25.             System.out.println(it.next());  
26.         }  
27.   
28.     }  
29.   
30. }  
输出结果如下:
abbabcjjjdacccgeeegfgr
由此可见,此时元素具备可比性,即按照其自然顺序进行排序。打开帮助文档,我们可以清晰的发现String已经实现了Comparable接口,并且已经覆盖了compareTo(),“这不是废话么^_^”,如图所示:
 
 
 
ps……如果我们要往TreeSet里添加的元素是自己刚刚定义的,我们也可以自己定义该元素的类实现Comparable接口,并且覆盖compareTo()方法,如下所示:代码2:
[java] view plain copy
1. package com.package1;  
2.   
3. import java.util.*;  
4.   
5. class Student implements Comparable//该接口强制让学生具备比较性。  
6. {  
7.     private String name;  
8.     private int age;  
9.   
10.     Student(String name,int age)  
11.     {  
12.         this.name = name;  
13.         this.age = age;  
14.     }  
15.   
16.     public int compareTo(Object obj)  
17.     {  
18.   
19.         //return 0;  
20.           
21.         if(!(obj instanceof Student))  
22.             throw new RuntimeException("不是学生对象");  
23.         Student s = (Student)obj;  
24.   
25.         //System.out.println(this.name+"....compareto....."+s.name);  
26.         if(this.age>s.age)  
27.             return 1;  
28.         if(this.age==s.age)  
29.         {  
30.             return this.name.compareTo(s.name);  
31.         }  
32.         return -1;  
33.         /**/  
34.     }  
35.   
36.     public String getName()  
37.     {  
38.         return name;  
39.   
40.     }  
41.     public int getAge()  
42.     {  
43.         return age;  
44.     }  
45. }  
46. public class TreeSet2   
47. {  
48.     public static void main(String[] args)   
49.     {  
50.         TreeSet ts = new TreeSet();  
51.   
52.         ts.add(new Student("lisi02",22));  
53.         ts.add(new Student("lisi02",21));  
54.         ts.add(new Student("lisi007",20));  
55.         ts.add(new Student("lisi09",19));  
56.         ts.add(new Student("lisi06",18));  
57.         ts.add(new Student("lisi06",18));  
58.         ts.add(new Student("lisi007",29));  
59.         //ts.add(new Student("lisi007",20));  
60.         //ts.add(new Student("lisi01",40));  
61.   
62.         Iterator it = ts.iterator();  
63.         while(it.hasNext())  
64.         {  
65.             Student stu = (Student)it.next();  
66.             System.out.println(stu.getName()+"..."+stu.getAge());  
67.         }  
68.     }  
69. }  
结果如下:
lisi06...18lisi09...19lisi007...20lisi02...21lisi02...22lisi007...29
此例子将学生元素,强行按照年龄来排序,这就是我们想要的排序方式。
 
第二种排序如下:
还是刚刚代码1的例子,我们使用第二种排序方式,使得String类型的元素按照长度来排序。
代码3:
[java] view plain copy
1. /* 
2.  * 使元素按照长度来排序,若长度相同,则按照自然排序。 
3.  */  
4. public class TreeSettest {  
5.   
6.     public static void main(String[] args) {  
7.         //创建对象  
8.         TreeSet ts=new TreeSet(new MyCompare());  
9.           
10.         //添加元素  
11.         ts.add("abc");  
12.         ts.add("bcc");  
13.         ts.add("das");  
14.         ts.add("bcde");  
15.         ts.add("asdfg");  
16.         ts.add("befqfca");  
17.           
18.         //进行迭代  
19.         Iterator it=ts.iterator();  
20.           
21.         //循环取出元素  
22.         while(it.hasNext())  
23.         {  
24.             System.out.println(it.next());  
25.         }  
26.   
27.     }  
28.   
29. }  
30.   
31. //定义一个类实现Comparator接口,并且覆盖compare()方法。  
32. class MyCompare implements Comparator  
33. {  
34.   
35.     @Override  
36.     public int compare(Object o1, Object o2) {  
37.         //进行强制类型转换  
38.         String s1=(String) o1;  
39.         String s2=(String) o2;  
40.           
41.         //进行比较  
42.         if(s1.length()>s2.length())  
43.             return 1;  
44.         if(s1.length()<s2.length())  
45.             return -1;  
46.         if(s1.length()==s2.length())  
47.         {  
48.             return s1.compareTo(s2);  
49.         }  
50.         return 0;  
51.     }  
52. }

结果如下:

abc
bcc
das
bcde
asdfg
befqfca

此种情况下,我们不方便修改源代码,而只需要修改比较方法时,我们就可以自己创建一个比较器。在建立TreeSet时,将比较器传入即可使元素按照特定比较方式输出。

 

总结:

Comparable(方式一)接口和Compartor(方式二)接口的比较:

 

         两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但

是需要修改源代码。

 

       用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把

比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其

可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

 

以上就介绍了JAVA的相关知识,希望对JAVA有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言JAVA频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程