------- android培训、java培训、期待与您交流! ----------
TreeSet会将元素自动排序。往该集合中存元素或者对象,实现排序,就必须是元素或者对象具备比较性,所以对象要实现Comparable接口,具有比较性
练习:将TreeSet集合中添加对象学生,按照学生的年龄进行排序
import java.util.*;
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet(); //新建一个TreeSet集合
//添加元素
ts.add(new student("zhangsan",20));
ts.add(new student("zhangsan1",21));
ts.add(new student("zhangsan2",22));
ts.add(new student("zhangsan3",22));
Iterator it=ts.iterator(); //引用迭代器遍历集合元素
while(it.hasNext())
{
student stu=(student)it.next(); //将集合中元素强转为Student类型,便于使用Student中的方法
System.out.println(stu.GetAge()+"----"+stu.GetName());
}
}
}
class student implements Comparable //学生实现Comparable接口,继而具有比较性
{
//引用name,age变量
private String name;
private int age;
student(String name,int age) //构造函数
{
//使name和age作用于整个类中
this.name=name;
this.age=age;
}
public String GetName() //获取姓名
{
return name;
}
public int GetAge() //获取年龄
{
return age;
}
public int compareTo(Object obj) //覆盖Comparable中的compareTo方法,构造属于学生的比较方法
{
if(!(obj instanceof student))
throw new RuntimeException("不是学生对象");
student s=(student)obj; //将传入对象强转为student类,
System.out.println(this.name+"---compareto---"+s.name);
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
//将姓名按照字典顺序排序
return this.name.compareTo(s.name); //<span style="color:#ff0000;">字符串本身就具备比较性,实现了Comparable接口,所以可以直接进行比较</span>
}
return -1;
// return 0;
}
}
TreeSet底层数据结构是二叉树
保证元素唯一性的依据:compareTo方法中的 return 0,该结果视为元素相同,所以只有一个会保留
以上就是TreeSet的第一种排序方法,让元素本身具备比较性,让元素对象实现Comparable接口。即为自然顺序
TreeSet第二种排序方式:让集合自身具备比较性,让集合按照指定的比较器进行比较。将比较器对象作为参数传给TreeSet集合的构造函数
定义一个类,实现comparator,重写compare(参数1,参数2)方法
import java.util.*;
class TreeSetDemo2
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet(new Mycompare());
ts.add(new Student("zhangsan",20));
ts.add(new Student("zhangsan1",21));
ts.add(new Student("zhangsan2",22));
ts.add(new Student("zhangsan3",20));
ts.add(new Student("zhangsan1",25));
Iterator it=ts.iterator(); //创建迭代器,遍历集合元素
while(it.hasNext())
{
Student stu=(Student)it.next();
System.out.println(stu.getName()+"----"+stu.getAge());
}
}
}
class Student //构造学生类
{
private String name;
private int age;
Student(String name,int age)
{
//构造函数将name,age运用到整个类中
this.name=name;
this.age=age;
}
public int getAge() //获取年龄
{
return age;
}
public String getName() //获取姓名
{
return name;
}
}
class Mycompare implements Comparator //自定义比较器类
{
public int compare(Object o1,Object o2) //重写Comparator的compare方法
{
//将传入对象强转为学生类
Student s1=(Student)o1;
Student s2=(Student)o2;
int num= (s1.getName().compareTo(s2.getName())); //此处的campareTo是使用String中的方法
if(num==0)
{
//因为Integer对象也实现了comparator接口,具备比较性,所以使用该对象比较年龄更加简洁
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); //将年龄封装成Integer对象使用比较方法
/*
if(s1.getAge()>s2.getAge())
return 1;
if(s1.getAge()==s2.getAge())
return 0;
return -1;
*/
}
return num;
}
}
当以上两种比较方法都存在时,以comparator比较器为主
二.泛型
泛型用于解决安全问题,是一个安全机制
好处:将运行时期出现问题classCastException(类型转换异常),转移到了编译时期,让运行时问题减少,更加安全;避免了强制转换的麻烦
泛型的格式:通过<>来定义要操作的引用数据类型。通常在在集合框架中很常见
import java.util.*;
class GenericDemo
{
public static void main(String[] args)
{
ArrayList <String> al=new ArrayList<String>(); //创建一个集合,并且使用泛型,参数基本类型是String类型的
//添加元素
al.add("abcd");
al.add("abcd987");
al.add("abcd75");
al.add("abcd087");
Iterator <String> it = al.iterator(); //使用迭代器遍历元素
while(it.hasNext())
{
String s=it.next();
System.out.println(s+s.length()); //打印元素和长度
}
}
}
按照集合中的字符串元素按照其长度比较排序,如果长度相同,再将字符串按照字典顺序排序
import java.util.*;
class GenericDemo2
{
public static void main(String[] args)
{
TreeSet <String> ts=new TreeSet<String>(new LenComparator()); //创建集合,泛型定义是String类型的,并传入比较器
//添加元素
ts.add("abcd");
ts.add("cc");
ts.add("aaa");
ts.add("z");
ts.add("hah");
Iterator<String> it=ts.iterator(); //使用迭代器
while(it.hasNext())
{
String s=it.next(); //获取集合中的元素
System.out.println(s);
}
}
}
class LenComparator implements Comparator<String> //构造长度比较器
{
public int compare(String o1,String o2) //重写compare方法
{
int num=new Integer(o1.length()).compareTo(new Integer(o2.length())); //使用Integer对象的比较方法
if(num==0)
return o2.compareTo(o1); //如果长度相等,再比较元素字符串本身
return num;
}
}
早期没有泛型时的工具类
import java.util.*;
class Tool
{
private Object obj;
public void setObject(Object obj) //设置对象
{
this.obj=obj;
}
public void getObject() //获取对象
{
return obj;
}
}
class GenericClass
{
public void main(String[] args)
{
Tool t=new Tool();
t.setObject(new Student()); //设置对象,传入一个Student对象
Student s=(Student)t.getObject(); //使用强转,获取学生对象
}
}
使用泛型类
class GenericClass
{
public void main(String[] args)
{
/*
Tool t=new Tool();
t.setObject(new Student()); //设置对象,传入一个Student对象
Student s=(Student)t.getObject(); //使用强转,获取学生对象
*/
Utils<worker> u=new Utils<worker>();
u.setObject(new Student());
worker w=u.getObject();
}
}
class Utils<QQ>
{
private QQ q;
public void setObject(QQ q) //设置对象
{
this.q=q;
}
public QQ getObject() //获取对象
{
return q;
}
}
当类中操作的引用数据类型不确定的时候,就使用泛型来完成扩展
泛型类定义的泛型,在整个类中都有效,如果被方法使用,所要操作的类型已经被固定,为了让不同方法可以操作不同类型,将泛型就定义在了方法上
import java.util.*;
class GenericDemo4
{
public static void main(String[] args)
{
Demo d=new Demo(); //创建Demo对象
//通过将泛型定义在方法上,传入不同参数
d.show("haha");
d.show(new Integer(4));
d.print("heihei");
}
}
class Demo
{
public <T> void show(T t) //将泛型定义在show方法上
{
System.out.println("show:"+t);
}
public <Q> void print(Q q) //将泛型定义在print方法上
{
System.out.println("print:"+q);
}
}
静态方法不可以访问类上定义的泛型
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。同时在类上定义泛型,类中方法如果使用不同泛型,不影响方法的使用
import java.util.*;
class GenericDemo4
{
public static void main(String[] args)
{
/*
Demo d=new Demo(); //创建Demo对象
//通过将泛型定义在方法上,传入不同参数
d.show("haha");
d.show(new Integer(4));
d.print("heihei");
*/
Demo<String> d=new Demo<String>(); //在类上定义泛型
d.show("haha");
d.print(4);
}
}
class Demo<T>
{
public <T> void show(T t) //将泛型定义在show方法上
{
System.out.println("show:"+t);
}
public static <Q> void print(Q q) //将泛型定义在print方法上
{
System.out.println("print:"+q);
}
}
泛型定义在接口上
import java.util.*;
class GenericDemo5
{
public static void main(String[] args)
{
In in=new In();
in.show("haha");
}
}
interface Inter<T> //创建接口和接口的show方法
{
void show(T t);
}
class In implements Inter<String> //新建一个类实现Inter接口,
{
public void show(String t) //复写show方法
{
System.out.println("show:"+t);
}
}
import java.util.*;
class GenericDemo5
{
public static void main(String[] args)
{
In in=new In(); //新建类
in.show("haha");
Inte<Integer> inte=new Inte<Integer>(); //新建泛型为Integer的类
inte.show(4);
}
}
interface Inter<T> //创建接口,泛型为String
{
void show(T t); //复写接口的show方法
}
class In implements Inter<String> //新建一个类实现Inter接口,
{
public void show(String t) //复写show方法
{
System.out.println("show:"+t);
}
}
class Inte<T> implements Inter<T> //将泛型定义在实现接口的类上
{
public void show(T t) //复写show方法
{
System.out.println("show:"+t);
}
}
?通配符,占位符
泛型限定 ?extends E 可以接收E类型或其子类 : 上限
?super E 可以接收E或其父类: 下限
import java.util.*;
class GenericDemo3
{
public static void main(String[] args)
{
/*
ArrayList<String> al=new ArrayList<String>(); //创建一个泛型为String类型的集合
//添加元素
al.add("abcq");
al.add("abcq");
al.add("abcq");
ArrayList<Integer> al1=new ArrayList<Integer>(); 创建一个泛型为String类型的集合
//添加元素
al1.add(4);
al1.add(5);
al1.add(9);
printColl(al);
printColl(al1);
*/
ArrayList<Person> al=new ArrayList<Person>(); //建立泛型为Person的集合
al.add(new Person("abd01"));
al.add(new Person("abd02"));
al.add(new Person("abd03"));
printColl(al);
ArrayList<Student> all=new ArrayList<Student>(); //建立泛型为Person的集合
all.add(new Student("abd--1"));
all.add(new Student("abd--2"));
all.add(new Student("abd--3"));
printColl(all);
}
//使用通配符“?”表示调用不明确的数据类型
public static void printColl(ArrayList<span style="color:#ff0000;"><? extends Person</span>> al) //将迭代器封装为一个方法,方便调用. 将泛型限定为Person和其子类
{
Iterator<<span style="color:#ff0000;">? extends Person</span>> it=al.iterator(); //使用迭代器, 将泛型限定为Person和其子类
while(it.hasNext())
{
System.out.println(it.next().getName());
}
}
}
class Person //定义Person类
{
private String name; //声明姓名变量
Person(String name)
{
this.name=name; //构造方法初始化姓名,将其作用于整个类中
}
public String getName()
{
return name;
}
}
class Student extends Person //定义学生类继承perosn类
{
Student(String name)
{
super(name); //构造函数初始化name引用父类变量
}
}
TreeSet中的泛型限定
import java.util.*;
class GenericDemo7
{
public static void main(String[] args)
{
TreeSet<Student> ts=new TreeSet<Student>(new Comp()); //创建泛型为学生的集合,将比较器传入
//添加元素
ts.add(new Student("abc-3"));
ts.add(new Student("abc-2"));
ts.add(new Student("abc-1"));
Iterator<Student> it=ts.iterator(); //使用迭代器,遍历元素
while(it.hasNext())
{
System.out.println(it.next().getName());
}
TreeSet<Worker> trs=new TreeSet<Worker>(new Comp()); //创建泛型为工人的集合,将比较器传入
//添加对象
trs.add(new Worker("wabc-3"));
trs.add(new Worker("wabc-2"));
trs.add(new Worker("wabc-1"));
Iterator<Worker> ite=trs.iterator(); //引用迭代器,遍历元素
while(ite.hasNext())
{
System.out.println(ite.next().getName());
}
}
}
class Comp implements Comparator<Person> //将比较器泛型定义为父类型,提高复用性
{
public int compare(Person s1,Person s2) //复写compare方法
{
return s1.getName().compareTo(s2.getName()); //使用String类的比较方法
}
}
class Person //定义Person类
{
private String name; //声明姓名变量
Person(String name)
{
this.name=name; //构造方法初始化姓名,将其作用于整个类中
}
public String getName()
{
return name;
}
}
class Student extends Person //定义学生类继承perosn类
{
Student(String name)
{
super(name); //构造函数初始化name引用父类变量
}
}
class Worker extends Person //定义工人类继承person类
{
Worker(String name)
{
super(name); //构造函数初始化name引用父类变量
}
}
总结,泛型限定就是为提高程序扩展性而使用的