TreeSet泛型.docx

上传人:b****6 文档编号:5383676 上传时间:2022-12-15 格式:DOCX 页数:12 大小:19.33KB
下载 相关 举报
TreeSet泛型.docx_第1页
第1页 / 共12页
TreeSet泛型.docx_第2页
第2页 / 共12页
TreeSet泛型.docx_第3页
第3页 / 共12页
TreeSet泛型.docx_第4页
第4页 / 共12页
TreeSet泛型.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

TreeSet泛型.docx

《TreeSet泛型.docx》由会员分享,可在线阅读,更多相关《TreeSet泛型.docx(12页珍藏版)》请在冰豆网上搜索。

TreeSet泛型.docx

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,这就说明我们给ArrayList传递了一个引用数据类型的参数,这个参数就是String,这告诉JDK说ArrayList里所装的引用元素的类型都是String类型的,如果你装的元素不是String类型,那么JDK在编译时就会给你报错。

在Jdk文档中的,这里的T、E只是个变量名,而它们的值是什么呢?

就是引用的数据类型,如String、Date等,这些就可以是这些T、E变量的值。

T代表类型,E代表元素。

其实这个字母可以随便取,只是一个变量名字而已。

又如Map集合中的,K代表key,V代表value。

只是一个变量名而已

什么时候定义泛型类?

当类中要操作的引用数据类型不确定的时候,

早期定义Object来完成扩展。

现在定义泛型来完成扩展。

泛型类

classUtils

{

publicvoidprint(Tt)

{

System.out.println(t);

}

}

在类中定义的泛型,这样的类叫“泛型类”,在类中定义的泛型,可以在整个类中使用,如我们在newUtils()时,我们传递了一个String类型,那么在类中任何地方出现的T代表的都是String,如print方法中的T就是String,这时在调用print方法时就只能传String类型的参数,否则就会报错

泛型方法

classUtils

{

publicvoidprint(Tt)

{

System.out.println(t);

}

}

在方法中定义的泛型,这样的方法叫“泛型方法”。

在方法中定义的泛型,在这个方法中使用,如publicvoidprint(。

),那么在这个方法中的参数就只能是Date类型。

也就是说你在<>中传递的是什么类型,方法中接受的参数就是什么类型的。

注:

在方法里定义的泛型只在该方法有效,所以多个方法里的泛型的变量名可以相同,如:

publicvoidprint(Tt){}

publicTgetObj(){}

注意1:

classUtils

{

publicstaticvoidprint(Tt)

{

System.out.println(t);

}

}

这样编写语法不正确,因为在调用print方法时,Utils对象还没产生,也就说还没定义呢?

所以入静态方法中的泛型必定是定义在方法上的。

方法泛型只能加在返回类型的前面,如:

publicstaticvoidprint(Tt){}这是正确的

publicstaticvoidprint(Tt){}这是错误的

注意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{}中传递的泛型类型是String,所以覆盖voidshow(Tt);方法中的T就是String,也就是必须覆盖publicvoidshow(Stringt)方法。

如果Demo3Impl在实现GenericDemo3接口时,也不知道会传给voidshow(Tt)方法中的参数是什么类型,那么Demo3Impl类也可以定义为泛型,如下:

classDemo3ImplimplementsGenericDemo3{

@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){

ArrayListal1=newArrayList();

ArrayListal2=newArrayList();

al1.add("ab");

al1.add("deab");

al1.add("eee");

al2.add(3);

al2.add(6);

al2.add(55);

printCollection(al1);

printCollection(al2);//会报错

}

publicstaticvoidprintCollection(ArrayListt){

Iteratorit=t.iterator();

while(it.hasNext()){

System.out.println(it.next());

}

}

}

上面例子中定义的printCollection方法只能接受的参数是:

ArrayList类型,如果所以printCollection(al2);会报错,要想这个方法能接受的参数不较通用,则可以用?

通配符,修改后的代码如下:

publicstaticvoidprintCollection(ArrayList

>t){

Iterator

>it=t.iterator();

while(it.hasNext()){

System.out.println(it.next());

}

}

这样printCollection(al2);就不会报错了。

其实这个通用的问题也可以用泛型方法来解决,代码如下:

publicstaticvoidprintCollection(ArrayListt){

Iteratorit=t.iterator();

while(it.hasNext()){

System.out.println(it.next());

}

}

区别在于?

只是一个占位符,无法引用,而则可以引用,如:

publicstaticvoidprintCollection(ArrayListt){

Iteratorit=t.iterator();

while(it.hasNext()){

Telement=it.next();//这里引用了T

System.out.println(element);

}

}

 

泛型中的范围限定:

假设有Person类、和Student类、Teacher类,Student继承了Person,Teacher类也继承了Person类,

ArrayListlist=newArrayList;

这样的语句是错误的,先看=号左边:

声明了一个只能存放Student的ArrayList引用变量list

再看=号右边:

new了一个能存放Persion的实例对象

那么右边的实例对象可以add(Teacher),因为Teacher是Person的子类,但是=号左边的引用变量明确声明了只能在放Student,所以这就有矛盾了,所以这个语句也是错误的。

ArrayListlist=newArrayList;

这样的语句是错误的,先看=号左边:

声明了一个能存放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){

ArrayListgrandpas=newArrayList();

ArrayListfathers=newArrayList();

ArrayListsons=newArrayList();

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)构造方法

TreeSetts=newTreeSet(newTestGeneric());

ts.add(newSon("abc"));

ts.add(newSon("ddd"));

ts.add(newSon("aaa"));

Iteratorit=ts.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中指定的E是什么类型就是什么类型,比如这个E指定为Son对象类型,那么Comparator

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[]){

TreeSetts1=newTreeSet(newStu4Comp());

ts1.add(newStudent4("abc03"));

ts1.add(newStudent4("abc02"));

ts1.add(newStudent4("abc06"));

ts1.add(newStudent4("abc01"));

Iteratorit1=ts1.iterator();

while(it1.hasNext())

{

System.out.println(it1.next().getName());

}

TreeSetts2=newTreeSet(newStu6Comp());

ts2.add(newStudent6("wabc--03"));

ts2.add(newStudent6("wabc--02"));

ts2.add(newStudent6("wabc--06"));

ts2.add(newStudent6("wabc--01"));

Iteratorit2=ts2.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有的方法。

展开阅读全文
相关搜索

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1