TreeSet泛型.docx
- 文档编号:5383676
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:12
- 大小:19.33KB
TreeSet泛型.docx
《TreeSet泛型.docx》由会员分享,可在线阅读,更多相关《TreeSet泛型.docx(12页珍藏版)》请在冰豆网上搜索。
TreeSet泛型
Set:
无序,不可以重复元素。
|--HashSet:
数据结构是哈希表。
线程是非同步的。
保证元素唯一性的原理:
判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。
|--TreeSet:
可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据:
compareTo方法return0.
TreeSet排序的第一种方式:
让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
因为此,在定义一个类的时候,如果这个类要进行存储的话,一般要覆盖hashCode、equals方法,并实例Comparator接口。
因为存到数据结构为哈希表的集合里要覆盖hashCode、equals方法,而存到数据结构为二叉树的,则需要实现Comparable接口,而且实现了该接口,还可以用Collections和Arrays的sort方法进行排序。
最好也让这个类成为一个JavaBean,这让使用更方便。
注:
当一个Student类具有可比较性(实现了Comparable接口),把它存到了TreeSet集合中,但是,它的自然排序不是我们想要的排序方式,这时就可以给TreeSet指定一个比较器(Comparator),则排序方式按比较器中的规则进行。
泛型:
(几乎所有的集合类都定义了泛型)
<>是用来传递引用数据的类型,如String类型、Date类型,又如
ArrayList
在Jdk文档中的
就是引用的数据类型,如String、Date等,这些就可以是这些T、E变量的值。
T代表类型,E代表元素。
其实这个字母可以随便取,只是一个变量名字而已。
又如Map集合中的
只是一个变量名而已
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,
早期定义Object来完成扩展。
现在定义泛型来完成扩展。
泛型类
classUtils
{
publicvoidprint(Tt)
{
System.out.println(t);
}
}
在类中定义的泛型,这样的类叫“泛型类”,在类中定义的泛型,可以在整个类中使用,如我们在newUtils
泛型方法
classUtils
{
public
{
System.out.println(t);
}
}
在方法中定义的泛型,这样的方法叫“泛型方法”。
在方法中定义的泛型,在这个方法中使用,如public
。
。
),那么在这个方法中的参数就只能是Date类型。
也就是说你在<>中传递的是什么类型,方法中接受的参数就是什么类型的。
注:
在方法里定义的泛型只在该方法有效,所以多个方法里的泛型的变量名可以相同,如:
public
public
注意1:
classUtils
{
publicstaticvoidprint(Tt)
{
System.out.println(t);
}
}
这样编写语法不正确,因为在调用print方法时,Utils对象还没产生,也就说
所以入静态方法中的泛型必定是定义在方法上的。
方法泛型只能加在返回类型的前面,如:
publicstatic
public
注意2:
classUtils
{
publicstaticvoidprint(Tt)
{
System.out.println(t);
}
}
classDemo
{
publicstaticvoidmain(Stringargs[])
{
Utilsutils=newUtils();
utils.print("abc");
}
}
在声明了泛型后,在使用时,如果没有传进泛型所需的值,那么变量
是Object,也就是说在上面Demo类中调用utils.print("abc");方法时,该方法的参数类型为Object,传进去的参数“abc”会被提升为Object。
接口中的泛型:
publicinterfaceGenericDemo3
voidshow(Tt);
}
classDemo3ImplimplementsGenericDemo3
@Override
publicvoidshow(Stringt){
System.out.println("abc");
}
publicstaticvoidmain(String[]args){
Demo3Impldemo=newDemo3Impl();
demo.show("abc");
}
}
上面的例子中Demo3Impl实现GenericDemo3,那么必须覆盖接口中的voidshow(Tt);方法,在classDemo3ImplimplementsGenericDemo3
如果Demo3Impl在实现GenericDemo3接口时,也不知道会传给voidshow(Tt)方法中的参数是什么类型,那么Demo3Impl类也可以定义为泛型,如下:
classDemo3Impl
@Override
publicvoidshow(Tt){
System.out.println(t);
}
publicstaticvoidmain(String[]args){
Demo3Impldemo=newDemo3Impl();
demo.show(newDate());
}
}
泛型中的?
通配符
packagecom.itheima.generic;
importjava.util.ArrayList;
importjava.util.Iterator;
publicclassGenericDemo4{
publicstaticvoidmain(String[]args){
ArrayList
ArrayList
al1.add("ab");
al1.add("deab");
al1.add("eee");
al2.add(3);
al2.add(6);
al2.add(55);
printCollection(al1);
printCollection(al2);//会报错
}
publicstaticvoidprintCollection(ArrayList
Iterator
while(it.hasNext()){
System.out.println(it.next());
}
}
}
上面例子中定义的printCollection方法只能接受的参数是:
ArrayList
通配符,修改后的代码如下:
publicstaticvoidprintCollection(ArrayList
>t){
Iterator
>it=t.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
这样printCollection(al2);就不会报错了。
其实这个通用的问题也可以用泛型方法来解决,代码如下:
publicstatic
Iterator
while(it.hasNext()){
System.out.println(it.next());
}
}
区别在于?
只是一个占位符,无法引用,而
publicstatic
Iterator
while(it.hasNext()){
Telement=it.next();//这里引用了T
System.out.println(element);
}
}
泛型中的范围限定:
假设有Person类、和Student类、Teacher类,Student继承了Person,Teacher类也继承了Person类,
ArrayList
这样的语句是错误的,先看=号左边:
声明了一个只能存放Student的ArrayList引用变量list
再看=号右边:
new了一个能存放Persion的实例对象
那么右边的实例对象可以add(Teacher),因为Teacher是Person的子类,但是=号左边的引用变量明确声明了只能在放Student,所以这就有矛盾了,所以这个语句也是错误的。
ArrayList
这样的语句是错误的,先看=号左边:
声明了一个能存放Person的ArrayList引用变量list
再看=号右边:
new了一个只能存放Student的实例对象
那么右边的实例对象只可以add(Student),但是=号左边的引用变量明确声明了能在放Person,所以这就有矛盾了,因为Teacher是Person的子类,按=左边的声明,应该是可以存进去的,但是右边的实例对象却又只能add(Student),所以这个语句也是错误的。
上限
extendsPerson>:
这个限定是说:
可以传递的类型为Person或Person的子类。
Person下面的子类不固定,而父类Perso己固定,所以叫上限
下限
superPerson>:
这个限定是说:
可以传递的类型为Person或Person的父类。
Person上面的父类不固定,而子类Person己固定,所以叫下限
这个上限、下限一般用在集合中,如:
上限实例:
packagecom.itheima.generic;
importjava.util.ArrayList;
importjava.util.Iterator;
classGrandpa{
publicStringname;
publicStringgetName(){
name="爷爷";
returnname;
}
}
classFatherextendsGrandpa{
publicStringgetName(){
name="爸爸";
returnname;
}
}
classSonextendsFather{
publicStringgetName(){
name="儿子";
returnname;
}
}
publicclassGenericDemo5{
publicstaticvoidmain(String[]args){
ArrayList
ArrayList
ArrayList
grandpas.add(newGrandpa());s
fathers.add(newFather());
sons.add(newSon());
//print1(grandpas);这个不符合要求
print1(fathers);
print1(sons);
}
publicstaticvoidprint1(ArrayList
extendsFather>al){//这个方法只能接受Father或Father的子类对象
Iterator
extendsFather>it=al.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}
}
}
下限实例:
publicclassGenericDemo6{
publicstaticvoidmain(String[]args){
//TreeSet中的TreeSet(Comparator
superE>c)构造方法
TreeSet
ts.add(newSon("abc"));
ts.add(newSon("ddd"));
ts.add(newSon("aaa"));
Iterator
while(it.hasNext()){
System.out.println(it.next().getName());
}
}
}
classTestGenericimplementsComparator
@Override
publicintcompare(Fathero1,Fathero2){
returno1.getName().compareTo(o2.getName());
}
}
TreeSet中的TreeSet(Comparator
superE>c)构造方法,这里的E是在TreeSet的类中定义的,也就是说newTreeSet
superE>中的E就是Son类型,也就是说这个Comparator参数中的泛型参数可以是Son或Son的父类(Father)。
当Father有多个儿子时对象时,而每个对象都要进行存储到TreeSet集合中,并且需要传递一个比较器(Comparator),这时这个比较器就可以传Father的比较器,这样的比较器对每个儿子都可以用。
要不然的话每个儿子都得指定一个比较器就很麻类了!
实例如下:
packagecom.itheima.generic;
importjava.util.Comparator;
importjava.util.Iterator;
importjava.util.TreeSet;
publicclassGenericDemo7{
publicstaticvoidmain(Stringargs[]){
TreeSet
ts1.add(newStudent4("abc03"));
ts1.add(newStudent4("abc02"));
ts1.add(newStudent4("abc06"));
ts1.add(newStudent4("abc01"));
Iterator
while(it1.hasNext())
{
System.out.println(it1.next().getName());
}
TreeSet
ts2.add(newStudent6("wabc--03"));
ts2.add(newStudent6("wabc--02"));
ts2.add(newStudent6("wabc--06"));
ts2.add(newStudent6("wabc--01"));
Iterator
while(it2.hasNext())
{
System.out.println(it2.next().getName());
}
}
}
classStu4CompimplementsComparator
{
publicintcompare(Student4s1,Student4s2)
{
returns1.getName().compareTo(s2.getName());
}
}
classStu6CompimplementsComparator
{
publicintcompare(Student6s1,Student6s2)
{
returns1.getName().compareTo(s2.getName());
}
}
classPerson
{
privateStringname;
Person(Stringname)
{
this.name=name;
}
publicStringgetName()
{
returnname;
}
publicStringtoString()
{
return"person:
"+name;
}
}
classStudent4extendsPerson
{
Student4(Stringname)
{
super(name);
}
}
classStudent6extendsPerson
{
Student6(Stringname)
{
super(name);
}
}
这里有一个Person类,它有两个儿子Student4、Student6,Student4和Student6都要保存到TreeSet集合中,因为分别为Student4、Student6各创建了一个比较器,如果说Person有很多的儿子都要进行添加到TreeSet集合中的话,那么得为每个儿子都创建一个比较器,那样比较麻类。
在TreeSet的构造函数中的这么一个构造函数:
TreeSet(Comparator
superE> c),所以我们可以创建一个父类的比较器,这样的比较器对每个儿子都通用,如下:
classPersonCompimplementsComparator
publicintcompare(Persons1,Persons2)
{
returns1.getName().compareTo(s2.getName());
}
}
这个比较器对每个儿子都通用,需要注意的是,Person只能调用Person有的方法。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TreeSet 泛型