十、泛型限定
一、TreeSet1.1、TreeSet
Set:hashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的HashCode值是否相同。
如果相同,还会判断元素的equals方法是否为true;
TreeSet: 可以去Set集合中的元素时行 排序。
使用二叉树的数据结构。
保证元素唯一性的依据:compareTo()方法return 0
使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator进行排序,具体取决于使用的构造方法。
示例一、
packagecom.pb.treeset.demo1;importjava.util.Iterator;importjava.util.TreeSet;/***
*@authorDenny
* TreeSet
* 可以对Set集合的元素进行自然排序
**/publicclassTreeSetDemo1 {publicstaticvoidmain(String[] args) {
TreeSet ts=newTreeSet();
ts.add("abc");
ts.add("aah");
ts.add("cda");
ts.add("bca");
ts.add("Dca");for(Iterator it=ts.iterator();it.hasNext();){
System.out.PRintln(it.next());
}
}
}
结果:
Dca
aah
abc
bca
cda
示例二、使用对象
二、Comparable
TreeSet排序:
第一种方式,让元素自身具备比较性,元素实现Comparable接口,重写compareTo()方法。自然顺序排序
2.1、Comparable接口
public interfaceComparable<T>
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。
使用TreeSet存多个对象时,要在该对象类中实现Comparable接口,以实现TreeSet的排序,不然就会报java.lang.ClassCastException:
cannot be cast to java.lang.Comparable
方法摘要int
compareTo(T o)
比较此对象与指定对象的顺序。
参数:o- 要比较的对象。返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。抛出:ClassCastException- 如果指定对象的类型不允许它与此对象进行比较。
排序时:当主要条件相同时,要判断次要条件。
packagecom.pb.treeset.demo1;publicclassPersonimplementsComparable{privateString name;//姓名privateintage;//年龄privateString gender;//性别publicPerson() {super();//TODO Auto-generated constructor stub}publicPerson(String name,intage, String gender) {super();this.name =name;this.age =age;this.gender =gender;
}publicString getName() {returnname;
}publicvoidsetName(String name) {this.name =name;
}publicintgetAge() {returnage;
}publicvoidsetAge(intage) {this.age =age;
}publicString getGender() {returngender;
}publicvoidsetGender(String gender) {this.gender =gender;
}//显示所有属性publicvoidshow(){
System.out.println("姓名:"+this.name+"........年龄:"+this.age+"...........性别:"+this.gender);
}/** 按照年龄大小排序,年龄相同按姓名排序*/@OverridepublicintcompareTo(Object obj) {if(!(objinstanceofPerson)){try{thrownewException("不是人类对象");
}catch(Exception e) {
e.printStackTrace();
}
}
Person p=(Person)obj;if(this.age>p.age){return1;
}elseif(this.age<p.age){return-1;
}else{returnthis.name.compareTo(p.name);
}
}
}
packagecom.pb.treeset.demo1;importjava.util.Iterator;importjava.util.TreeSet;publicclassTreeSetDemo2 {publicstaticvoidmain(String[] args) {
Person p1=newPerson("lisi007",19,"man");
Person p2=newPerson("lisi003",20,"woman");
Person p3=newPerson("zhangsan002",19,"man");
Person p4=newPerson("abc009",20,"woman");
Person p5=newPerson("ndd011",19,"man");
Person p6=newPerson("QQ005",16,"woman");//声明TreeSet集合TreeSet<Person>ts=newTreeSet<Person>();//添加对象元素ts.add(p1);
ts.add(p2);
ts.add(p3);
ts.add(p4);
ts.add(p5);
ts.add(p6);//遍历for(Iterator<Person> it=ts.iterator();it.hasNext();){
Person p=it.next();
p.show();
}
}
}
结果:
姓名:qq005........年龄:16...........性别:woman
姓名:lisi007........年龄:19...........性别:man
姓名:ndd011........年龄:19...........性别:man
姓名:zhangsan002........年龄:19...........性别:man
姓名:abc009........年龄:20...........性别:woman
姓名:lisi003........年龄:20...........性别:woman
示例:如果按存入顺序取出只需要CompareTo方法return 1
packagecom.pb.treeset.demo1;publicclassPersonimplementsComparable{privateString name;//姓名privateintage;//年龄privateString gender;//性别publicPerson() {super();//TODO Auto-generated constructor stub}publicPerson(String name,intage, String gender) {super();this.name =name;this.age =age;this.gender =gender;
}publicString getName() {returnname;
}publicvoidsetName(String name) {this.name =name;
}publicintgetAge() {returnage;
}publicvoidsetAge(intage) {this.age =age;
}publicString getGender() {returngender;
}publicvoidsetGender(String gender) {this.gender =gender;
}//显示所有属性publicvoidshow(){
System.out.println("姓名:"+this.name+"........年龄:"+this.age+"...........性别:"+this.gender);
}/** 按照年龄大小排序,年龄相同按姓名排序*/@OverridepublicintcompareTo(Object obj) {//存出顺序return1;//倒序//return -1//如果返回0就只有一个元素}
}
三、3.1、实现指定的比较器实现Comparator 接口,重写compare方法
第二种方式:当元素自身不具备比较性时或者具备的比较性不是所需要的。
这里就需要让集合自身具备比较性。
在集合初始化,就有了比较方式。
构造方法摘要TreeSet()
构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。
TreeSet(Collection<? extends E> c)
构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。
TreeSet(Comparator<? super E> comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。
TreeSet(SortedSet<E> s)
构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。
定义比较器,将比较器对象 作为参数转递给集合TreeSet的构造方法
示例一、
packagecom.pb.treeset.demo2;publicclassPerson{privateString name;//姓名privateintage;//年龄privateString gender;//性别publicPerson() {super();//TODO Auto-generated constructor stub}publicPerson(String name,intage, String gender) {super();this.name =name;this.age =age;this.gender =gender;
}publicString getName() {returnname;
}publicvoidsetName(String name) {this.name =name;
}publicintgetAge() {returnage;
}publicvoidsetAge(intage) {this.age =age;
}publicString getGender() {returngender;
}publicvoidsetGender(String gender) {this.gender =gender;
}//显示所有属性publicvoidshow(){
System.out.println("姓名:"+this.name+"........年龄:"+this.age+"...........性别:"+this.gender);
}
}
比较器
packagecom.pb.treeset.demo2;importjava.util.Comparator;/*** 比较器,实现Comparator接口,
* 并重写compare方法
*@authorAdministrator
**/publicclassMyComparetorimplementsComparator<Person>{/** 按姓名排序,如果姓名相同,按年龄排序*/@Overridepublicintcompare(Person p1, Person p2) {//比较姓名intnum=p1.getName().compareTo(p2.getName());//如果姓名相同if(num==0){//比较年龄returnnewInteger(p1.getAge()).compareTo(newInteger(p2.getAge()));
}//返回结果returnnum;
}
}
packagecom.pb.treeset.demo2;importjava.util.Iterator;importjava.util.TreeSet;publicclassTreeSetDemo3 {publicstaticvoidmain(String[] args) {//声明TreeSet集合,并将比较器传入构造方法TreeSet<Person> ts=newTreeSet<Person>(newMyComparetor());//添加元素ts.add(newPerson("lisi010",21,"man"));
ts.add(newPerson("lisi010",19,"man"));
ts.add(newPerson("lisi007",21,"woman"));
ts.add(newPerson("lisi002",16,"man"));
ts.add(newPerson("lisi022",21,"woman"));
ts.add(newPerson("lisi010",16,"man"));//遍历for(Iterator<Person> it=ts.iterator();it.hasNext();){
Person p=it.next();
p.show();
}
}
}
姓名:lisi002........年龄:16...........性别:man
姓名:lisi007........年龄:21...........性别:woman
姓名:lisi010........年龄:16...........性别:man
姓名:lisi010........年龄:19...........性别:man
姓名:lisi010........年龄:21...........性别:man
姓名:lisi022........年龄:21...........性别:woman
示例二、
packagecom.pb.treeset.demo2;importjava.util.Comparator;importjava.util.Iterator;importjava.util.TreeSet;/** 按照字符串长度排序*/publicclassTreeSetDemo4 {publicstaticvoidmain(String[] args) {
TreeSet<String> ts=newTreeSet<String>(newMyCompare());
ts.add("abcd");
ts.add("cc");
ts.add("cba");
ts.add("Cba");
ts.add("z");
ts.add("NBA");
ts.add("hehe");
ts.add("A");for(Iterator<String> it =ts.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}/** 比较器*/classMyCompareimplementsComparator<String>{
@Overridepublicintcompare(String s1, String s2) {//比较长度intlen=newInteger(s1.length()).compareTo(newInteger(s2.length()));//如果长度相同,比较内容if(len==0){returns1.compareTo(s2);
}returnlen;
}
}
四、泛型4.1、泛型概述
JDK1.5出现新特性,用于解决安全问题,是一个安全机制
如:ArrayList<String> a1=new ArrayList<String>();
声明一个字符串类型的arraylist容器,只能存String类型
优点:将运行时期出现的问题ClassCastException,转移到了编译时期。
方便程序员解决问题,让运行时问题送减少,同时安全。
避免了强制类型转换麻烦。
packagecom.pb.fanxing.demo1;importjava.util.ArrayList;importjava.util.Iterator;publicclassArryListDemo1 {publicstaticvoidmain(String[] args) {//声明一个Arraylist集合,只能存放String类型ArrayList<String> al=newArrayList<String>();
al.add("abcd");
al.add("adc");
al.add("NBA");
al.add("CFO");//遍历Iterator<String> it=al.iterator();while(it.hasNext()){
String str=it.next();
System.out.println(str);
}
}
}
五、泛型使用5.1、使用泛型
通过<>来定义泛型
通常在集合框架中很常见,只要见到<>就要定义泛型。
其它泛型<>就是用来接收类型的。
当使用集合时,将集合要存储的数据类型作为参数传递到<>中.
packagecom.pb.fanxing.demo1;importjava.util.Comparator;importjava.util.Iterator;importjava.util.TreeSet;//倒序排列publicclassDemo2 {publicstaticvoidmain(String[] args) {
TreeSet<String> ts=newTreeSet<String>(newMyCompare());
ts.add("abcd");
ts.add("cc");
ts.add("cba");
ts.add("Cba");
ts.add("z");
ts.add("NBA");
ts.add("hehe");
ts.add("A");for(Iterator<String> it =ts.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}/** 比较器*/classMyCompareimplementsComparator<String>{
@Overridepublicintcompare(String s1, String s2) {//比较长度//倒序排列intlen=newInteger(s2.length()).compareTo(newInteger(s1.length()));//如果长度相同,比较内容if(len==0){returns2.compareTo(s1);
}returnlen;
}
}
hehe
abcd
cba
NBA
Cba
cc
z
A
六、泛型类6.1、泛型类的使用
packagecom.pb.fanxing.demo2;/*** 当类中要操作的引用数据类型不确定的时候
* 早期定主Object来完成扩展
* 现在定义泛型来完成扩展
**/classPerson{privateString name;privateintage;publicPerson() {super();//TODO Auto-generated constructor stub}publicPerson(String name,intage) {super();this.name =name;this.age =age;
}publicString getName() {returnname;
}publicvoidsetName(String name) {this.name =name;
}publicintgetAge() {returnage;
}publicvoidsetAge(intage) {this.age =age;
}
}classStudentextendsPerson{privateintid;publicintgetId() {returnid;
}publicvoidsetId(intid) {this.id =id;
}
}/** 泛型类*/classUtils<T>{privateT t;publicvoidsetT(T t){this.t=t;
}publicT getT(){returnt;
}
}publicclassGenericDemo1 {publicstaticvoidmain(String[] args) {
Utils<Person> u=newUtils<Person>();
u.setT(newPerson("张三",23));
Person person=u.getT();
System.out.println(person.getName()+"......"+person.getAge());
}
}
泛型类定义的泛型,在整个类中有效,如果被方法使用
泛型类的对象明克要操作的具体类型后,所有 要操作的类型已经固定
七、泛型方法7.1、泛型类的方法
为了让不同方法可以操作不同类型,而且类型还不确定,
可以将泛型定义在方法上
packagecom.pb.fanxing.demo2;/*** 泛型方法
**/classDemo{public<T>voidshow(T t){
System.out.println("show:"+t);
}public<T>voidprint(T t){
System.out.println("print:"+t);
}
}publicclassGenericDemo2 {publicstaticvoidmain(String[] args) {
Demo d=newDemo();
d.show(4);
d.print("hehe");
d.show("hello");
d.print(3.4);
}
}
结果:
show:4print:hehe
show:hello
print:3.4
八、静态泛型方法8.1、静态泛型方法
静态方法不可以访问类上定义的泛型。
如果静态方法访问的类型不确定,可以将泛型定义在方法上
packagecom.pb.fanxing.demo2;classTool<T>{//和类上的泛型一至public<T>voidshow(T t){
System.out.println("show:"+t);
}//单独的和类上的不一样,但也可以使用类上的public<Q>voidprint(Q q){
System.out.println("print:"+q);
}//单独的和类上的不一样因为是static的,不能和类上的一样publicstatic<W>voidmethod(W t){
System.out.println("static:"+t);
}
}publicclassGenericStaticDemo {publicstaticvoidmain(String[] args) {//定义字符串Tool<String> t=newTool<String>();//传入字符串t.show("hehe");//传入字符串t.print("dfsds");//传入doublet.print(2323.3);//传入字符串t.method("ffff");//传入intt.method(222);
}
}
结果:
show:hehe
print:dfsds
print:2323.3static:ffffstatic:222
九、泛型接口9.1、泛型接口
packagecom.pb.fanxing.demo2;interfaceTest<T>{publicvoidshow(T t);
}classTestImpl<T>implementsTest<T>{
@Overridepublicvoidshow(T t) {
System.out.println(t);
}
}publicclassGenericDemo3 {publicstaticvoidmain(String[] args) {
Test<String> test=newTestImpl<String>();
test.show("hello");
Test<Integer> test1=newTestImpl<Integer>();
test1.show(332);
}
}
十、泛型限定10.1、泛型限定
使用<?>来占位
packagecom.pb.fanxing.demo2;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassGenericDemo4 {publicstaticvoidmain(String[] args) {
List<String> list=newArrayList<String>();
list.add("aa");
list.add("ab");
list.add("ac");
List<Integer> list1=newArrayList<Integer>();
list1.add(3);
list1.add(1);
list1.add(5);
print(list);
print(list1);
}/*public static void print(List<?> list){ //不确定类型
Iterator<?> it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}*///使用泛型Tpublicstatic<T>voidprint(List<T> list){//不确定类型Iterator<T> it=list.iterator();while(it.hasNext()){
T t=it.next();//使用泛型可以操作对象System.out.println(t);
}
}
}
aa
ab
ac
3
1
5
10.2、上限和下限
?:通配符,也可以理解为占位符。
泛型的限定
<? extends E>:可以接收E类型 或者E的子类 上限
<? super E> 可以接收E类型或者E的父类型。下限
packagecom.pb.fanxing.demo2;importjava.util.ArrayList;importjava.util.Iterator;classPerson{privateString name;privateintage;publicPerson(String name,intage){this.name=name;this.age=age;
}publicString getName(){returnname;
}publicintgetAge(){returnage;
}
}classStudentextendsPerson{publicStudent(String name,intage){super(name,age);
}
}publicclassGenericDemo5 {publicstaticvoidmain(String[] args) {
ArrayList<Person> a1=newArrayList<Person>();
a1.add(newPerson("abc1",23));
a1.add(newPerson("abc2",13));
a1.add(newPerson("abc3",33));
ArrayList<Student> a2=newArrayList<Student>();
a2.add(newStudent("abc--1",23));
a2.add(newStudent("abc--2",13));
a2.add(newStudent("abc--3",33));
print(a1);
print(a2);
}publicstaticvoidprint(ArrayList<?extendsPerson> list){//代表Person和Person的子类Iterator<?extendsPerson> it=list.iterator();while(it.hasNext()){
Person p=it.next();
System.out.println(p.getName()+"..."+p.getAge());
}
}
}//结果abc1...23abc2...13abc3...33abc--1...23abc--2...13abc--3...33
下限
packagecom.pb.fanxing.demo2;importjava.util.ArrayList;importjava.util.Comparator;importjava.util.Iterator;importjava.util.Set;importjava.util.TreeSet;classPerson{privateString name;privateintage;publicPerson(String name,intage){this.name=name;this.age=age;
}publicString getName(){returnname;
}publicintgetAge(){returnage;
}
}classStudentextendsPerson{publicStudent(String name,intage){super(name,age);
}
}publicclassGenericDemo5 {publicstaticvoidmain(String[] args) {
TreeSet<Student> ts=newTreeSet<Student>(newMyCompare());
ts.add(newStudent("abc--5",23));
ts.add(newStudent("abc--2",13));
ts.add(newStudent("abc--3",33));
print(ts);
}publicstaticvoidprint(Set<?extendsPerson> list){//代表Person和Person的子类Iterator<?extendsPerson> it=list.iterator();while(it.hasNext()){
Person p=it.next();
System.out.println(p.getName()+"..."+p.getAge());
}
}
}classMyCompareimplementsComparator<Person>{
@Overridepublicintcompare(Person p1, Person p2) {returnp1.getName().compareTo(p2.getName());
}
}//结果:abc--2...13abc--3...33abc--5...23