16Set集合.docx
- 文档编号:28743403
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:21
- 大小:211.78KB
16Set集合.docx
《16Set集合.docx》由会员分享,可在线阅读,更多相关《16Set集合.docx(21页珍藏版)》请在冰豆网上搜索。
16Set集合
Set集合
1.Set接口
1.1.Set接口介绍
Set接口是Collection接口下的一个子接口。
它和List接口相同,都是Collection的子接口。
区别:
List:
有脚本、可以重复、拥有特有的ListIterator迭代器
Set:
没有脚本、不能包含重复元素,没有特有的迭代器,只能使用Iterator进行遍历。
2.HashSet集合
Set接口没有自己的特有的方法,所有方法全部来自于Collection接口。
重点学习Set接口下的两个实现类:
HashSet:
TreeSet:
此类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。
它不保证set的迭代顺序;特别是它不保证该顺序恒久不变。
此类允许使用null元素。
HashSet集合的底层使用的哈希表结构。
2.1.哈希表介绍
如果多个对象它们计算出的哈希值相同,这时在计算机中称为哈希冲突。
如果哈希值相同了,这时必须调用对象的equals方法比较2个对象(多个对象)是否是同一个对象。
任何给哈希表中存储的对象都应该具备hashCode和equals方法。
/*
*演示HashSet集合
*/
publicclassHashSetDemo{
publicstaticvoidmain(String[]args){
//创建集合对象
HashSetset=newHashSet();
//添加元素
set.add("bbb");
set.add("cccc");
set.add("cccc");
set.add("abc");
set.add("abc");
//遍历HashSet集合
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
2.2.HashSet保存自定义对象
/*
*演示给HashSet中保存自定义类的对象
*/
publicclassHashSetDemo2{
publicstaticvoidmain(String[]args){
//创建集合对象
HashSetset=newHashSet();
//创建自定义对象
//Personp=newPerson("华安",23);
//set.add(p);
set.add(newPerson("华安",23));
set.add(newPerson("华安",23));
set.add(newPerson("秋香",18));
set.add(newPerson("9527",23));
set.add(newPerson("小书童",33));
//遍历
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
分析:
我们自己定义了一个Person类,然后创建Person对象,将这些Person对象存储到HashSet集合中。
希望同姓名和年龄的Person对象,应该是同一个人,在集合中只能有一个。
但是通过程序发现依然可以保存多个同姓名和年龄的Person对象。
HashSet集合底层使用的哈希表,给哈希表中存储对象的时候,需要调用当前对象自己的hashCode计算位置,equals判断对象是否相同。
而我们的Person类继承了Object类,自然就会具备hashCode和equals方法。
但是Person类中并没有去复写hashCode和equals方法,说明在将Person对象给HashSet集合中保存的时候,调用的hashCode和equals方法依然使用的Object类中的方法。
Object类中的equals方法是在比较2个对象的地址值是否相同。
hashCode方法计算哈希值的是也是根据对象的地址值在进行计算。
如果创建了多个Person对象,它们的姓名和年龄相同,我们认为应该是同一个人,但是由于是new了多次,在堆中就会有多个Person对象,它们的地址值肯定是不相同的。
2.3.HashSet保证对象唯一的原因
HashSet保证对象的唯一依赖当前给HashSet集合中保存的对象的hashCode和equals方法。
使用hashCode计算位置,使用equals比较2个对象是否相同。
2.4.HashSet总结
要保证给HashSet集合中存储的自定义对象中的数据唯一,自定义对象所属的类需要复写Object类中的hashCode和equals方法。
2.5.LinkedHashSet介绍
HashSet集合不保证存取的顺序,保证对象唯一。
LinkedHashSet它是HashSet集合的子类,它也属于Set接口下的集合容器,同样也能保证对象的唯一。
和HashSet的区别是:
LinkedHashSet可以保证存放的元素的存取顺序一致。
LinkedHashSet它没有自己的特有方法,所有方法全部来自于父类。
/*
*演示LinkedHashSet集合
*/
publicclassLinkedHashSetDemo{
publicstaticvoidmain(String[]args){
//创建集合对象
LinkedHashSetset=newLinkedHashSet();
set.add("ccc");
set.add("aaa");
set.add("abc");
set.add("ccc");
set.add("aaa");
//遍历
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
3.TreeSet介绍
3.1.TreeSet介绍
基于TreeMap的NavigableSet实现。
使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator进行排序,具体取决于使用的构造方法。
TreeSet集合它是Set接口的间接实现类。
TreeSet集合它也不能存放重复的元素。
TreeSet集合的底层使用的数据结构中的二叉树(红黑树)结构。
这种数据结构可以对保存在其中的数据进行排序。
3.2.TreeSet演示
/*
*TreeSet集合的简单演示
*/
publicclassTreeSetDemo{
publicstaticvoidmain(String[]args){
//创建集合对象
TreeSetset=newTreeSet();
//添加元素
set.add("ddd");
set.add("aaa");
set.add("bbb");
set.add("bbb");
set.add("abc");
set.add("ABC");
set.add("ABC");
set.add("aBC");
set.add("eee");
set.add("def");
set.add("def");
set.add("ddf");
set.add("ddf");
//遍历
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
通过程序发现存放在TreeSet集合中的所有字符串都进行排序。
3.3.树结构介绍
介绍数据结构中的树结构:
树结构:
二叉树:
每个节点最多只能有2个子节点。
非规则二叉树:
有点节点可能会有2个子节点,有的只有一个。
甚至没有。
普通的树结构:
非规则树结构。
二叉树:
3.4.TreeSet保存自定义对象
如果将自定义对象存储到TreeSet集合(二叉树结构)中,这时底层会将传递的这个对象强制转成Comparable类型。
发生上述的原因是:
给TreeSet中保存的对象需要进行比较大小,然后确定它们在二叉树中存储位置,存储的对象就必须具备比较大小的功能。
如果要使一个对象具备比较大小的功能,这个对象所属的类需要实现Java中提供的Comparable接口。
实现其中的compareTo方法。
/*
*演示给TreeSet集合中保存自定义对象
*/
publicclassTreeSetDemo2{
publicstaticvoidmain(String[]args){
//创建TreeSet集合对象
TreeSetset=newTreeSet();
set.add(newPerson("华安",23));
set.add(newPerson("华安",23));
set.add(newPerson("秋香",13));
set.add(newPerson("秋香",23));
set.add(newPerson("石榴",33));
//遍历
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
将对象保存到TreeSet集合中过程中:
在将对象保存到集合中的时候,需要将当前这个对象和集合中已经存在的对象进行大小比较,也就是去调用对象的compareTo方法。
如果这个方法返回的结果是零,就说明当前正要往集合中存储的对象和已经在集合中的对象大小一样。
这时这个对象就不会被保存到集合中。
3.5.Comparable介绍使用
/*
*让我们自己的类实现Comparable接口,让其对象具备比较大小的功能
*/
publicclassPersonimplementsComparable{
privateStringname;
privateintage;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
@Override
publicStringtoString(){
return"Person[name="+name+",age="+age+"]";
}
/*
*实现Comparable接口中的compareTo方法
*需要在compareTo方法中根据对象的属性数据进行大小的比较
*
*compareTo方法的调用时间:
*当正要给TreeSet中保存对象的时候,由TreeSet集合的底层,会将
*当前这个对象强转成Comparable类型,然后再用强转后的这个对象
*调用compareTo方法,将已经在集合中的对象传递Objecto,然后
*在compareTo方法中比较当前正要存放的对象和已经在集合中的对象的大小。
*/
publicintcompareTo(Objecto){
//判断传递进来的o是否是Person类型
if(!
(oinstanceofPerson)){
//判断成立,说明当前传递进来的o不是Person类型
thrownewClassCastException("传递的对象不是Person类型");
}
Personp=(Person)o;
/*
//比较
if(this.age==p.age){
//年龄相同,判断姓名
if(this.name.equals(p.name)){
//判断成立说明年龄和姓名都相同认为是同一个人
return0;
}else{
returnpareTo(p.name);
}
}else{
returnthis.age-p.age;
}
*/
inttemp=this.age-p.age;
returntemp==0?
pareTo(p.name):
temp;
}
}
3.6.比较器介绍
3.6.1.比较器介绍
需求:
将字符串数据保到TreeSet集合中,要求按照字符串的长度进行排序。
“AAAAA”“aaa”
分析:
本身TreeSet集合可以对存放在其中的任何对象进行排序,依赖的是对象自己的compareTo方法。
String类本身已经具备compareTo方法,但是这个方法是按照字符串中每个字符的编码值大小进行比较。
而需求要求按照字符串的长度进行比较。
String类中的compareTo方法不能满足需求。
针对上述的问题,本身应该可以定义一个新的类,继承String类,复写compareTo方法,然后使用子类自己的比较方式。
但是由于String类被final修饰,不能再有子类。
Java给出另外一种处理方案:
如果对象自身具备了比较功能,或者对象自身根本就没有比较功能,这时依然需要对这些对象进行排序,我们可以自己创建一个专门负责比较对象大小的新的比较器对象。
3.6.2.比较器演示
/*
*演示使用比较器对TreeSet集合中的元素(对象)进行比较大小排序
*/
publicclassTreeSetDemo3{
publicstaticvoidmain(String[]args){
//没有传递比较器,会按照元素自身的compareTo进行大小比较
//TreeSetset=newTreeSet();
//传递比较器
TreeSetset=newTreeSet(newMyComparator());
set.add("AAAAA");
set.add("aaa");
set.add("aa");
set.add("AAA");
set.add("AAAAA");
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
//自定义比较器(自己定义比较规则)
publicclassMyComparatorimplementsComparator{
//实现按照字符串长度比较大小
publicintcompare(Objecto1,Objecto2){
//按照长度比较
if(!
(o1instanceofString&&o2instanceofString)){
thrownewClassCastException("数据类型不统一,无法比较");
}
Strings1=(String)o1;
Strings2=(String)o2;
inttemp=s1.length()-s2.length();
returntemp==0?
pareTo(s2):
temp;
}
}
3.6.3.Comparator和Comparable总结
相同点:
Comparator和Comparable:
它们都可以提供比较大小的方法。
不同点:
Comparable:
它是让某个类具备比较功能,当创建出这个类的对象,就可以直接使用这个对象中的compareTo方法进行比较大小。
Comparable是让对象自己具备了比较功能
Comparator:
它是提供比较两个对象大小,但是这个功能和对象自身并没有任何的关系。
只要将需要比较的两个对象传递给compare方法即可。
提供单独的比较器对象,可以比较任意的两个对象
4.Collection下的集合总结
集合:
存储对象。
Collection接口:
它中定义了操作集合的最共性的规则(增、删、判断、遍历)
List接口:
定义了拥有下标(索引)的所有集合共性的操作规则。
它中定义的方法都是围绕集合的下标设计的。
其中提供了(增、删、改、查、判断、遍历)。
它下面的集合可以存储重复的元素。
可以保证存取的顺序。
ArrayList:
底层是可变数组。
增删慢,查询快。
不同安全。
LinkedList:
底层是链表结构,有头和尾,其中设计了头尾的增删改查方法。
增删快,查询慢,不安全
Vector:
底层是可变数组,JDK1.0时出现,什么(增删,查询)都慢,安全。
被ArrayList代替。
Set接口:
它只能保存存储在集合中的元素唯一。
它中没有特有的方法,所有方法全部来自于Collection接口。
HashSet:
底层是哈希表,存放在其中的元素需要根据元素自身的hashCode方法计算在哈希表中存储的位置,根据equals方法比较两个对象是否相同。
给HashSet集合中保存的对象必须复写Object类中的hashCode和equals方法。
不保证存取的顺序。
不安全的。
LinkedHashSet:
底层是哈希表和链表。
没有自己的方法,全部都继承于HashSet。
它可以保证元素存取顺序。
不安全。
TreeSet:
底层是二叉树,存放在其中的元素可以进行排序。
排序就需要存储在其中的元素必须具备比较大小的功能。
因此要求给TreeSet集合中保存的对象自身所属的类应该实现Comparable接口,这样对象自身就会具备compareTo方法,在给TreeSet集合中保存的时候,就可以进行比较大小,进而就能够排序。
5.TreeSet存储对象保证类型统一
/*
*思考:
TreeSet集合中能否存储类型不一致的对象?
*/
publicclassTreeSetDemo{
publicstaticvoidmain(String[]args){
TreeSetset=newTreeSet();
set.add("aaa");
set.add("AAA");
set.add("ccc");
/*
*保存Integer对象
*当把Integer类型的123给TreeSet集合中存储的时候,
*这时Integer对象就会调用自己的compareTo方法,会将已经在集合中的其他
*对象传递给自己的compareTo方法,但是由于集合中的其他数据是String类型的
*在传递给Integer类中的compareTo方法的时候,需要将String类型的对象
*转成Integer类型的对象,由于String类型的数据不能直接强转成Integer
*这样导致再给TreeSet集合中保存数据时发生了异常。
*/
set.add(123);
set.add(23);
set.add(213);
//遍历
for(Iteratorit=set.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
TreeSet集合中保存对象的时候:
1、如果多个不同类型的对象它们之间没有继承关系,这时是不能同时存储到同一个TreeSet集合中
2、如果多个不同类型的对象,它们之间有继承关系,并且父类已经实现了Comparable接口,这时这些父类对象和子类对象都可以给TreeSet集合中保存。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 16 Set 集合