01 TreeSet
02 TreeSet存储自定义对象
03 二叉树
04 实现Comparator方式排序
05 TreeSet练习
06 泛型概述
07 泛型使用
08 泛型类
09 泛型方法
10 静态方法泛型
11 泛型接口
12 泛型限定
13 泛型限定2
01 TreeSet
|--Set
|--HashSet
|--TreeSet 可以对集合中的元素进行排序
1 import java.util.*;
2 class TreeSetTest
3 {
4 public static void main(String[] args)
5 {
6 TreeSet ts=new TreeSet();
7 ts.add("asd");
8 ts.add("sdfff");
9 ts.add("abc");
10 ts.add("Das");
11
12 Iterator it=ts.iterator();
13 while(it.hasNext())
14 {
15 System.out.println(it.next());
16 }
17
18
19 }
20 }
输出是:(按照ASCII码的顺序排序)
Das abc asd sdfff(实际有换行)
02 TreeSet存储自定义对象
|--Set
|--HashSet
|--TreeSet 可以对集合中的元素进行排序
需求:向TreeSet集合中存贮自定义对象学生
想要根据学生的年龄大小排序。
java中只有实现Comparable接口的类的对象才是可比较的,TreeSet才能对其排序。
注意,排序时,当主要因素相同时,就比较次要因素。
1 import java.util.*;
2 class TreeSetTest2
3 {
4 public static void main(String[] args)
5 {
6 TreeSet ts=new TreeSet();
7 ts.add(new Student("wangwu01",12));
8 ts.add(new Student("wangwu02",44));
9 ts.add(new Student("wangwu03",16));
10 ts.add(new Student("wangwu05",52));
11 ts.add(new Student("wangwu07",22));
12 ts.add(new Student("wangwu08",22));
13
14
15 Iterator it=ts.iterator();
16 while(it.hasNext())
17 {
18 Student stu=(Student)it.next();
19 System.out.println(stu.getName()+"::"+stu.getAge());
20 }
21
22
23 }
24 }
25 class Student implements Comparable
26 {
27 private String name;
28 private int age;
29 public Student(String name,int age)
30 {
31 this.name=name;
32 this.age=age;
33 }
34 public String getName(){return name;}
35 public int getAge(){return age;}
36
37 public int compareTo(Object obj)
38 {
39 //用compareTo方法比较后,如果return 0,就视为是相同的对象,不会重复存入
40 //所以,要注意,主要因素相同时,还要比较次要因素才行
41 if(!(obj instanceof Student))
42 throw new RuntimeException("不是学生类!");
43 Student stu=(Student)obj;
44 if(this.age>stu.getAge())
45 return 1;
46 if(this.age==stu.getAge())
47 //String类型也实现了Comparable接口
48 return this.name.compareTo(stu.getName());
49 return -1;
50 }
51 }
03 二叉树
|--TreeSet 可以对集合中的元素进行排序
底层的数据结构是二叉树
保证元素唯一性的依据:
compareTo方法 return 0
二叉排序树:比根元素小的元素作为左孩子节点,比根元素大的元素作为右孩子结点。
作用:减少比较次数,提高排序效率。
04 实现Comparator方式排序
TreeSet排序的第一种方式:让元素自身具备比较性,
元素需要实现Comparable接口,覆盖compareTo方法。
这种方式也成为元素的自然顺序,或者默认顺序。
TreeSet的第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的时候,
这是就需要让集合自身具备比较性。
定义了比较器,将比较器对象作为参宿传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
比较器的定义:定义一个类,实现Comparator接口,覆盖compare方法。
写项目一定要留有接口,以便以后扩展其他功能。
新需求:按照学生的姓名排序。
分析:由于元素自身的比较性是按照年龄排序,不是我们所需要的。
所以要使用TreeSet第二种比较方式,定义一个比较器。
代码如下:(Student类省略)
1 import java.util.*;
2 class TreeSetTest3
3 {
4 public static void main(String[] args)
5 {
6 TreeSet ts=new TreeSet(new myCompare());
7 ts.add(new Student("wangwu01",12));
8 ts.add(new Student("wangwu02",44));
9 ts.add(new Student("wangwu05",16));
10 ts.add(new Student("wangwu05",52));
11 ts.add(new Student("wangwu07",22));
12 ts.add(new Student("wangwu07",22));
13
14
15 Iterator it=ts.iterator();
16 while(it.hasNext())
17 {
18 Student stu=(Student)it.next();
19 System.out.println(stu.getName()+"::"+stu.getAge());
20 }
21
22
23 }
24 }
25 class myCompare implements Comparator
26 {
27 public int compare(Object o1,Object o2)
28 {
29 if(!(o1 instanceof Student && o2 instanceof Student))
30 throw new RuntimeException("有参数不是学生类!");
31 Student s1=(Student)o1;
32 Student s2=(Student)o2;
33
34 int num=s1.getName().compareTo(s2.getName());
35 //如果按姓名排是相同的,就要继续比较其年龄
36 if(num==0)
37 {
38 return (new Integer(s1.getAge())).compareTo(s2.getAge());//return (s1.getAge()-s2.getAge());
39 }
40 return num;
41 }
42 }
05 TreeSet练习
本练习中比较器也可以定义成匿名内部类。
1 /*
2 练习:按照字符串长度排序。
3 分析:字符串的自然排序不符合需求,所以使用TreeSet第二中排序方法,定义比较器
4 */
5 import java.util.*;
6 class TreeSetTest4
7 {
8 public static void main(String[] args)
9 {
10 TreeSet ts=new TreeSet(new StrLenComparator() );
11 ts.add("qwe");
12 ts.add("qde");
13
14 ts.add("z");
15 ts.add("cv");
16 ts.add("wdsea");
17
18 Iterator it=ts.iterator();
19 while(it.hasNext())
20 {
21 System.out.println(it.next());
22 }
23 }
24 }
25 class StrLenComparator implements Comparator
26 {
27 public int compare(Object o1,Object o2)
28 {
29 if(!(o1 instanceof String && o2 instanceof String))
30 throw new RuntimeException("有对象不是字符串类型!");
31 String s1=(String)o1;
32 String s2=(String)o2;
33
34 int num=(new Integer(s1.length())).compareTo(s2.length());
35 //如果字符串长度相同,再比较其内容
36 if(num==0)
37 return s1.compareTo(s2);
38 return num;
39
40 }
41 }
06 泛型概述
泛型:JDK 1.5版本以后出现的新特性,用于解决安全问题,是一个安全机制。
(升级的原因:高效,简化,安全)
优点:
1.将运行时期出现的问题ClassCastException,转移到了编译时期,
便于程序员解决问题,使运行时的问题减少,更加安全。
2.避免了强制转换的麻烦。
1 import java.util.*;
2 class GenericDemo
3 {
4 public static void main(String[] args)
5 {
6 //在创建集合时,就为集合中的元素指明类型,
7 //一旦存入错误的类型,编译时就会报错
8 ArrayList<String> al=new ArrayList<String>();
9
10 al.add("asss01");
11 al.add("edcc");
12 al.add("edscs");
13
14 //为迭代器指明类型
15 //就不用强制转换了
16 Iterator<String> it=al.iterator();
17 while(it.hasNext())
18 {
19 String s=it.next();
20 System.out.println(s+":"+s.length());
21 }
22 }
23 }
07 泛型使用
泛型格式:通过<>来定义要操作的引用数据类型
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见。只要见到<>就要定义泛型。
其实<>就是用来接受类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
1 import java.util.*;
2 class GenericDemo2
3 {
4 public static void main(String[] args)
5 {
6 TreeSet<String> ts=new TreeSet<String>(new LenStrComparator());
7 ts.add("assd");
8 ts.add("df");
9 ts.add("er");
10 ts.add("dfg");
11
12 Iterator<String> it=ts.iterator();
13 while(it.hasNext())
14 {
15 String s=it.next();
16 System.out.println(s);
17 }
18
19 }
20 }
21 class LenStrComparator implements Comparator<String>//添加泛型,避免了compare方法中强转的麻烦
22 {
23 public int compare(String s1,String s2)
24 {
25 //如果想按字符串长度降序输出,则调换s1,s2位置。
26 int num=(new Integer(s1.length())).compareTo(new Integer(s2.length()));
27 if(num==0)
28 return s1.compareTo(s2);
29 return num;
30 }
31 }
08 泛型类
泛型类:
什么时候定义泛型类?
当类中要操作的引用数据类型不确定时,
早期定义Object来完成扩展
现在定义泛型来完成。
1 import java.util.*;
2 class Student
3 {
4 }
5 class Worker
6 {
7 }
8 //泛型出现前的用法
9
10 class Tool
11 {
12 private Object obj;
13 public void setObject(Object obj)
14 {
15 this.obj=obj;
16 }
17 public Object getObject()
18 {return obj;}
19 }
20 //使用泛型的做法
21 class Utils<T>
22 {
23 private T t;
24 public void setObject(T t)
25 {
26 this.t=t;
27 }
28 public T getObject()
29 {
30 return t;
31 }
32 }
33 class GenericDemo3
34 {
35
36 public static void main(String[] args)
37 {
38 Utils<Worker> u=new Utils<Worker>();
39 Worker w=u.getObject();//不再需要强转了
40
41 /*Tool t=new Tool();
42 t.setObject(new Student());
43 Worker w=(Worker)t.getObject();
44 */
45 }
46 }
09 泛型方法
泛型类定义的泛型,在整个类中有效,如果被方法使用,
那么泛型类的对象明确要操作的数据类型后,所有要操作的类型就已经固定了。
为了让不同的方法可以操作不同的类型,而且类型不确定,
那么可以将泛型定义在方法上。
1 import java.util.*;
2 class Demo
3 {
4 public <T> void show(T t)
5 {
6 System.out.println("show:"+t);
7 }
8 public <Q> void print(Q q)
9 {
10 System.out.println("print:"+q);
11 }
12 }
13 class GenericDemo4
14 {
15 public static void main(String[] args)
16 {
17 Demo d=new Demo();
18 d.show(4);//装箱,拆箱
19 d.print("hahaha");
20
21 }
22 }
10 静态方法泛型
特殊:
静态方法不可以使用定义在类上的泛型(无法从静态上下文中引用非静态)
如果静态方法操作的方法不确定,可以把泛型定义在方法上。
注意泛型在方法头部中的位置,在修饰符后,返回值类型之前,例如 public static <T> void method()。
11 泛型接口
1 /*
2 泛型定义在接口上
3 */
4 import java.util.*;
5 interface Inter<T>
6 {
7 public void show(T t);
8 }
9 class InterImp<T> implements Inter<T>
10 {
11 public void show(T t)
12 {
13 System.out.println(t);
14 }
15 }
16 class GenericDemo5
17 {
18 public static void main(String[] args)
19 {
20 InterImp<Integer> i=new InterImp<Integer>();
21 i.show(5);
22 }
23 }
12 泛型限定
? 通配符,也可以理解为占位符
应用1:
1 import java.util.*;
2 class GenericDemo6
3 {
4 public static void main(String[] args)
5 {
6 ArrayList<String> al=new ArrayList<String>();
7 al.add("abc1");
8 al.add("abc2");
9 al.add("abc3");
10 al.add("abc4");
11
12 ArrayList<Integer> al1=new ArrayList<Integer>();
13 al1.add(2);
14 al1.add(5);
15 al1.add(6);
16
17 printColl(al);
18 printColl(al1);
19
20
21 }
22 public static void printColl(ArrayList<?> al)//使用通配符,可以操作不同类型的对象。也可以用T
23 {
24 Iterator<?> it=al.iterator();
25 while(it.hasNext())
26 {
27 System.out.println(it.next());
28 }
29 }
30 }
应用2:
泛型的限定
? extends E:可以接受E类型或者E类型的子类,上限。
? super E:可以接受E类型或者E类型的父类,下限。
用到? extends E中的地方:
Collection接口中 :boolean addAll(Collection<? extends e> c)
用到? super E中的地方:
TreeSet类中 :TreeSet(Comparator<?super e> comparator)
1 import java.util.*;
2 class GenericDemo6
3 {
4 public static void main(String[] args)
5 {
6 ArrayList<Person> al=new ArrayList<Person>();
7 al.add(new Person("abc01"));
8 al.add(new Person("abc02"));
9 al.add(new Person("abc03"));
10 al.add(new Person("abc04"));
11
12 //printColl(al);
13
14 ArrayList<Student> al1=new ArrayList<Student>();
15 al1.add(new Student("abc--01"));
16 al1.add(new Student("abc--02"));
17 al1.add(new Student("abc--03"));
18 al1.add(new Student("abc--04"));
19 printColl(al1);
20 //ArrayList<Person> al=new ArrayList<Student>();Error!
21 //Person p=new Student();正确的,多态
22 //ArrayList<Student> al=new ArrayList<Person>(); 也是错误的! 要一致
23
24 }
25 public static void printColl(ArrayList<? extends Person> al)
26 {
27 Iterator<? extends Person> it=al.iterator();
28 while(it.hasNext())
29 {
30 System.out.println(it.next().getName());
31 }
32 }
33 }
34 class Person
35 {
36 private String name;
37 public Person(String name)
38 {
39 this.name=name;
40 }
41 public String getName()
42 {
43 return name;
44 }
45 }
46 class Student extends Person implements Comparable<Person>//<? super E>
47 {
48 public Student(String name)
49 {
50 super(name);
51 }
52 public int compareTo(Person p)
53 {
54 return (this.getName()).compareTo(p.getName());
55 }
56 }
13 泛型限定2
泛型限定是扩展用的。
? super E的例子
TreeSet(Comparator<? super E> comparator)一个类父类的比较器类也可用作这个类构造方法的参数
这个例子中Student类和Worker类就都用了它们父类Person的比较器Comp类
1 import java.util.*;
2 class GenericDemo7
3 {
4 public static void main(String[] args)
5 {
6 TreeSet<Student> ts1=new TreeSet<Student>(new Comp());
7 ts1.add(new Student("qaz1"));
8 ts1.add(new Student("qaz3"));
9 ts1.add(new Student("qaz6"));
10
11 Iterator<Student> it=ts1.iterator();
12 while(it.hasNext())
13 {
14 System.out.println(it.next().getName());
15 }
16
17 TreeSet<Worker> ts2=new TreeSet<Worker>(new Comp());
18 ts2.add(new Worker("w--qaz1"));
19 ts2.add(new Worker("w--qaz3"));
20 ts2.add(new Worker("w--qaz6"));
21
22 Iterator<Worker> it2=ts2.iterator();
23 while(it2.hasNext())
24 {
25 System.out.println(it2.next().getName());
26 }
27 }
28
29 }
30 class Person
31 {
32 private String name;
33 public Person(String name)
34 {
35 this.name=name;
36 }
37 public String getName()
38 {
39 return name;
40 }
41
42 public String toString()
43 {
44 return "person:"+name;
45 }
46 }
47 class Comp implements Comparator<Person>
48 {
49 public int compare(Person p1,Person p2)
50 {
51 return (p2.getName()).compareTo(p1.getName());//降序排列
52 }
53 }
54 class Student extends Person
55 {
56 public Student(String name)
57 {
58 super(name);
59 }
60
61 }
62 class Worker extends Person
63 {
64 public Worker(String name)
65 {
66 super(name);
67 }
68 }