1、TreeSet泛型Set:无序,不可以重复元素。 |-HashSet:数据结构是哈希表。线程是非同步的。 保证元素唯一性的原理:判断元素的hashCode值是否相同。 如果相同,还会继续判断元素的equals方法,是否为true。 |-TreeSet:可以对Set集合中的元素进行排序。 底层数据结构是二叉树。 保证元素唯一性的依据: compareTo方法return 0. TreeSet排序的第一种方式:让元素自身具备比较性。 元素需要实现Comparable接口,覆盖compareTo方法。 也种方式也成为元素的自然顺序,或者叫做默认顺序。 TreeSet的第二种排序方式。 当元素自身不具
2、备比较性时,或者具备的比较性不是所需要的。 这时就需要让集合自身具备比较性。 在集合初始化时,就有了比较方式。因为此,在定义一个类的时候,如果这个类要进行存储的话,一般要覆盖hashCode、equals方法,并实例Comparator接口。因为存到数据结构为哈希表的集合里要覆盖hashCode、equals方法,而存到数据结构为二叉树的,则需要实现Comparable接口,而且实现了该接口,还可以用Collections和Arrays的sort方法进行排序。最好也让这个类成为一个JavaBean,这让使用更方便。注:当一个Student类具有可比较性(实现了Comparable接口),把它存
3、到了TreeSet集合中,但是,它的自然排序不是我们想要的排序方式,这时就可以给TreeSet指定一个比较器(Comparator),则排序方式按比较器中的规则进行。泛型:(几乎所有的集合类都定义了泛型)是用来传递引用数据的类型,如String类型、Date类型,又如ArrayList,这就说明我们给ArrayList传递了一个引用数据类型的参数,这个参数就是String,这告诉JDK说ArrayList里所装的引用元素的类型都是String类型的,如果你装的元素不是String类型,那么JDK在编译时就会给你报错。在Jdk文档中的、,这里的T、E只是个变量名,而它们的值是什么呢?就是引用的数
4、据类型,如String、Date等,这些就可以是这些T、E变量的值。T代表类型,E代表元素。其实这个字母可以随便取,只是一个变量名字而已。又如Map集合中的,K代表key,V代表value。只是一个变量名而已什么时候定义泛型类?当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。现在定义泛型来完成扩展。泛型类class Utils public void print(T t) System.out.println(t); 在类中定义的泛型,这样的类叫“泛型类”,在类中定义的泛型,可以在整个类中使用,如我们在new Utils()时,我们传递了一个String类型,那么在类中
5、任何地方出现的T代表的都是String ,如print方法中的T就是String,这时在调用print方法时就只能传String类型的参数,否则就会报错泛型方法class Utils public void print(T t) System.out.println(t); 在方法中定义的泛型,这样的方法叫“泛型方法”。在方法中定义的泛型,在这个方法中使用,如public void print(。),那么在这个方法中的参数就只能是Date类型。也就是说你在中传递的是什么类型,方法中接受的参数就是什么类型的。注:在方法里定义的泛型只在该方法有效,所以多个方法里的泛型的变量名可以相同,如:publ
6、ic void print(T t)public T getObj()注意1:class Utils public static void print(T t) System.out.println(t); 这样编写语法不正确,因为在调用print方法时,Utils对象还没产生,也就说还没定义呢?所以入静态方法中的泛型必定是定义在方法上的。方法泛型只能加在返回类型的前面,如:public static void print(T t)这是正确的public static void print(T t)这是错误的注意2:class Utils public static void print(T
7、t) System.out.println(t); class Demo public static void main(String args) Utils utils = new Utils(); utils.print(abc); 在声明了泛型后,在使用时,如果没有传进泛型所需的值,那么变量的值是什么呢?是Object,也就是说在上面Demo类中调用utils.print(abc);方法时,该方法的参数类型为Object,传进去的参数“abc”会被提升为Object。接口中的泛型:public interface GenericDemo3 void show(T t);class Dem
8、o3Impl implements GenericDemo3 Override public void show(String t) System.out.println(abc); public static void main(String args) Demo3Impl demo = new Demo3Impl(); demo.show(abc); 上面的例子中Demo3Impl实现GenericDemo3,那么必须覆盖接口中的void show(T t);方法,在class Demo3Impl implements GenericDemo3中传递的泛型类型是String,所以覆盖voi
9、d show(T t);方法中的T就是String,也就是必须覆盖public void show(String t)方法。如果Demo3Impl在实现GenericDemo3接口时,也不知道会传给void show(T t)方法中的参数是什么类型,那么Demo3Impl类也可以定义为泛型,如下:class Demo3Impl implements GenericDemo3 Override public void show(T t) System.out.println(t); public static void main(String args) Demo3Impl demo = new
10、 Demo3Impl(); demo.show(new Date(); 泛型中的?通配符package com.itheima.generic;import java.util.ArrayList;import java.util.Iterator;public class GenericDemo4 public static void main(String args) ArrayList al1 = new ArrayList(); ArrayList al2 = new ArrayList(); al1.add(ab); al1.add(deab); al1.add(eee); al2.
11、add(3); al2.add(6); al2.add(55); printCollection(al1); printCollection(al2);/会报错 public static void printCollection(ArrayList t) Iterator it = t.iterator(); while(it.hasNext() System.out.println(it.next(); 上面例子中定义的printCollection方法只能接受的参数是:ArrayList类型,如果所以printCollection(al2);会报错,要想这个方法能接受的参数不较通用,则可
12、以用?通配符,修改后的代码如下: public static void printCollection(ArrayList t) Iterator it = t.iterator(); while(it.hasNext() System.out.println(it.next(); 这样printCollection(al2);就不会报错了。其实这个通用的问题也可以用泛型方法来解决,代码如下: public static void printCollection(ArrayList t) Iterator it = t.iterator(); while(it.hasNext() System
13、.out.println(it.next(); 区别在于?只是一个占位符,无法引用,而则可以引用,如: public static void printCollection(ArrayList t) Iterator it = t.iterator(); while(it.hasNext() T element = it.next();/这里引用了T System.out.println(element); 泛型中的范围限定:假设有Person类、和Student类、Teacher类,Student继承了Person,Teacher类也继承了Person类,ArrayList list = n
14、ew ArrayList;这样的语句是错误的,先看 = 号左边:声明了一个只能存放Student的ArrayList引用变量list 再看 = 号右边:new 了一个能存放Persion的实例对象 那么右边的实例对象可以add(Teacher),因为Teacher是Person的子类,但是 = 号左边的引用变量明确声明了只能在放Student,所以这就有矛盾了,所以这个语句也是错误的。ArrayList list = new ArrayList;这样的语句是错误的,先看 = 号左边:声明了一个能存放Person的ArrayList引用变量list 再看 = 号右边:new 了一个只能存放Stu
15、dent的实例对象 那么右边的实例对象只可以add(Student),但是 = 号左边的引用变量明确声明了能在放Person,所以这就有矛盾了,因为Teacher是Person的子类,按 = 左边的声明,应该是可以存进去的,但是右边的实例对象却又只能add(Student),所以这个语句也是错误的。上限 :这个限定是说:可以传递的类型为Person或Person的子类。Person下面的子类不固定,而父类Perso己固定,所以叫上限下限 :这个限定是说:可以传递的类型为Person或Person的父类。Person上面的父类不固定,而子类Person己固定,所以叫下限这个上限、下限一般用在集合
16、中,如:上限实例:package com.itheima.generic;import java.util.ArrayList;import java.util.Iterator;class Grandpa public String name; public String getName() name = 爷爷; return name; class Father extends Grandpa public String getName() name = 爸爸; return name; class Son extends Father public String getName() na
17、me = 儿子; return name; public class GenericDemo5 public static void main(String args) ArrayList grandpas= new ArrayList(); ArrayList fathers= new ArrayList(); ArrayList sons= new ArrayList(); grandpas.add(new Grandpa();s fathers.add(new Father(); sons.add(new Son(); / print1(grandpas); 这个不符合要求 print1
18、(fathers); print1(sons); public static void print1(ArrayList al)/这个方法只能接受Father或Father的子类对象 Iterator it = al.iterator(); while(it.hasNext() System.out.println(it.next().getName(); 下限实例:public class GenericDemo6 public static void main(String args) /TreeSet中的TreeSet(Comparator c) 构造方法 TreeSet ts = ne
19、w TreeSet(new TestGeneric(); ts.add(new Son(abc); ts.add(new Son(ddd); ts.add(new Son(aaa); Iterator it = ts.iterator(); while(it.hasNext() System.out.println(it.next().getName(); class TestGeneric implements Comparator Override public int compare(Father o1, Father o2) return o1.getName().compareTo(
20、o2.getName(); TreeSet中的TreeSet(Comparator c) 构造方法,这里的E是在TreeSet的类中定义的,也就是说new TreeSet中指定的E是什么类型就是什么类型,比如这个E指定为Son对象类型,那么Comparator中的E就是Son类型,也就是说这个Comparator参数中的泛型参数可以是Son或Son的父类(Father)。当Father有多个儿子时对象时,而每个对象都要进行存储到TreeSet集合中,并且需要传递一个比较器(Comparator),这时这个比较器就可以传Father的比较器,这样的比较器对每个儿子都可以用。要不然的话每个儿子都得
21、指定一个比较器就很麻类了!实例如下:package com.itheima.generic;import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;public class GenericDemo7 public static void main(String args) TreeSet ts1 = new TreeSet(new Stu4Comp(); ts1.add(new Student4(abc03); ts1.add(new Student4(abc02); ts1.add(new
22、Student4(abc06); ts1.add(new Student4(abc01); Iterator it1 = ts1.iterator(); while(it1.hasNext() System.out.println(it1.next().getName(); TreeSet ts2 = new TreeSet(new Stu6Comp(); ts2.add(new Student6(wabc-03); ts2.add(new Student6(wabc-02); ts2.add(new Student6(wabc-06); ts2.add(new Student6(wabc-0
23、1); Iterator it2 = ts2.iterator(); while(it2.hasNext() System.out.println(it2.next().getName(); class Stu4Comp implements Comparator public int compare(Student4 s1,Student4 s2) return s1.getName().compareTo(s2.getName(); class Stu6Comp implements Comparator public int compare(Student6 s1,Student6 s2
24、) return s1.getName().compareTo(s2.getName(); class Person private String name; Person(String name) this.name = name; public String getName() return name; public String toString() return person :+name; class Student4 extends Person Student4(String name) super(name); class Student6 extends Person Stu
25、dent6(String name) super(name); 这里有一个Person类,它有两个儿子Student4、Student6,Student4和Student6都要保存到TreeSet集合中,因为分别为Student4、Student6各创建了一个比较器,如果说Person有很多的儿子都要进行添加到TreeSet集合中的话,那么得为每个儿子都创建一个比较器,那样比较麻类。在TreeSet的构造函数中的这么一个构造函数:TreeSet(Comparatorc),所以我们可以创建一个父类的比较器,这样的比较器对每个儿子都通用,如下:class PersonComp implements Comparator public int compare(Person s1,Person s2) return s1.getName().compareTo(s2.getName(); 这个比较器对每个儿子都通用,需要注意的是,Person只能调用Person有的方法。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1