JAVA基础学习day15--集合二 TreeSet和泛型
一、TreeSet
1.1、TreeSet
Set:hashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的HashCode值是否相同。
如果相同,还会判断元素的equals方法是否为true;
TreeSet: 可以去Set集合中的元素时行 排序。
使用二叉树的数据结构。
保证元素唯一性的依据:compareTo()方法return 0
使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator
进行排序,具体取决于使用的构造方法。
示例一、
package com.pb.treeset.demo1; import java.util.Iterator; import java.util.TreeSet; /** * * @author Denny * TreeSet * 可以对Set集合的元素进行自然排序 * */ public class TreeSetDemo1 { public static void main(String[] args) { TreeSet ts=new TreeSet(); 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 interface Comparable<T>
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
使用TreeSet存多个对象时,要在该对象类中实现Comparable接口,以实现TreeSet的排序,不然就会报java.lang.ClassCastException:
cannot be cast to java.lang.Comparable
方法摘要 | |
---|---|
int |
compareTo(T o) 比较此对象与指定对象的顺序。 |
- 参数:
o
- 要比较的对象。- 返回:
- 负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
- 抛出:
ClassCastException
- 如果指定对象的类型不允许它与此对象进行比较。
排序时:当主要条件相同时,要判断次要条件。
package com.pb.treeset.demo1; public class Person implements Comparable{ private String name;//姓名 private int age;//年龄 private String gender;//性别 public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, int age, String gender) { super(); this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } //显示所有属性 public void show(){ System.out.println("姓名:"+this.name+"........年龄:"+this.age+"...........性别:"+this.gender); } /* * 按照年龄大小排序,年龄相同按姓名排序 */ @Override public int compareTo(Object obj) { if(!(obj instanceof Person)){ try { throw new Exception("不是人类对象"); } catch (Exception e) { e.printStackTrace(); } } Person p=(Person)obj; if(this.age>p.age){ return 1; }else if(this.age<p.age){ return -1; }else{ return this.name.compareTo(p.name); } } }
package com.pb.treeset.demo1; import java.util.Iterator; import java.util.TreeSet; public class TreeSetDemo2 { public static void main(String[] args) { Person p1=new Person("lisi007",19,"man"); Person p2=new Person("lisi003",20,"woman"); Person p3=new Person("zhangsan002",19,"man"); Person p4=new Person("abc009",20,"woman"); Person p5=new Person("ndd011",19,"man"); Person p6=new Person("qq005",16,"woman"); //声明TreeSet集合 TreeSet<Person>ts=new TreeSet<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
package com.pb.treeset.demo1; public class Person implements Comparable{ private String name;//姓名 private int age;//年龄 private String gender;//性别 public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, int age, String gender) { super(); this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } //显示所有属性 public void show(){ System.out.println("姓名:"+this.name+"........年龄:"+this.age+"...........性别:"+this.gender); } /* * 按照年龄大小排序,年龄相同按姓名排序 */ @Override public int compareTo(Object obj) { //存出顺序 return 1; //倒序 //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的构造方法
示例一、
package com.pb.treeset.demo2; public class Person{ private String name;//姓名 private int age;//年龄 private String gender;//性别 public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, int age, String gender) { super(); this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } //显示所有属性 public void show(){ System.out.println("姓名:"+this.name+"........年龄:"+this.age+"...........性别:"+this.gender); } }
比较器
package com.pb.treeset.demo2; import java.util.Comparator; /** * 比较器,实现Comparator接口, * 并重写compare方法 * @author Administrator * */ public class MyComparetor implements Comparator<Person>{ /* * 按姓名排序,如果姓名相同,按年龄排序 */ @Override public int compare(Person p1, Person p2) { //比较姓名 int num=p1.getName().compareTo(p2.getName()); //如果姓名相同 if(num==0){ //比较年龄 return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge())); } //返回结果 return num; } }
package com.pb.treeset.demo2; import java.util.Iterator; import java.util.TreeSet; public class TreeSetDemo3 { public static void main(String[] args) { //声明TreeSet集合,并将比较器传入构造方法 TreeSet<Person> ts=new TreeSet<Person>(new MyComparetor()); //添加元素 ts.add(new Person("lisi010",21,"man")); ts.add(new Person("lisi010",19,"man")); ts.add(new Person("lisi007",21,"woman")); ts.add(new Person("lisi002",16,"man")); ts.add(new Person("lisi022",21,"woman")); ts.add(new Person("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
示例二、
package com.pb.treeset.demo2; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /* * 按照字符串长度排序 */ public class TreeSetDemo4 { public static void main(String[] args) { TreeSet<String> ts=new TreeSet<String>(new MyCompare()); 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()); } } } /* * 比较器 */ class MyCompare implements Comparator<String>{ @Override public int compare(String s1, String s2) { //比较长度 int len=new Integer(s1.length()).compareTo(new Integer(s2.length())); //如果长度相同,比较内容 if(len==0){ return s1.compareTo(s2); } return len; } }
四、泛型
4.1、泛型概述
JDK1.5出现新特性,用于解决安全问题,是一个安全机制
如:ArrayList<String> a1=new ArrayList<String>();
声明一个字符串类型的arraylist容器,只能存String类型
优点:将运行时期出现的问题ClassCastException,转移到了编译时期。
方便程序员解决问题,让运行时问题送减少,同时安全。
避免了强制类型转换麻烦。
package com.pb.fanxing.demo1; import java.util.ArrayList; import java.util.Iterator; public class ArryListDemo1 { public static void main(String[] args) { //声明一个Arraylist集合,只能存放String类型 ArrayList<String> al=new ArrayList<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、使用泛型
通过<>来定义泛型
通常在集合框架中很常见,只要见到<>就要定义泛型。
其它泛型<>就是用来接收类型的。
当使用集合时,将集合要存储的数据类型作为参数传递到<>中.
package com.pb.fanxing.demo1; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; //倒序排列 public class Demo2 { public static void main(String[] args) { TreeSet<String> ts=new TreeSet<String>(new MyCompare()); 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()); } } } /* * 比较器 */ class MyCompare implements Comparator<String>{ @Override public int compare(String s1, String s2) { //比较长度 //倒序排列 int len=new Integer(s2.length()).compareTo(new Integer(s1.length())); //如果长度相同,比较内容 if(len==0){ return s2.compareTo(s1); } return len; } }
hehe
abcd
cba
NBA
Cba
cc
z
A
六、泛型类
6.1、泛型类的使用
package com.pb.fanxing.demo2; /** * 当类中要操作的引用数据类型不确定的时候 * 早期定主Object来完成扩展 * 现在定义泛型来完成扩展 * */ class Person{ private String name; private int age; public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } class Student extends Person{ private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } /* * 泛型类 */ class Utils<T>{ private T t; public void setT(T t){ this.t=t; } public T getT(){ return t; } } public class GenericDemo1 { public static void main(String[] args) { Utils<Person> u=new Utils<Person>(); u.setT(new Person("张三",23)); Person person=u.getT(); System.out.println(person.getName()+"......"+person.getAge()); } }
泛型类定义的泛型,在整个类中有效,如果被方法使用
泛型类的对象明克要操作的具体类型后,所有 要操作的类型已经固定
七、泛型方法
7.1、泛型类的方法
为了让不同方法可以操作不同类型,而且类型还不确定,
可以将泛型定义在方法上
package com.pb.fanxing.demo2; /** * 泛型方法 * */ class Demo{ public<T> void show(T t){ System.out.println("show:"+t); } public <T> void print(T t){ System.out.println("print:"+t); } } public class GenericDemo2 { public static void main(String[] args) { Demo d=new Demo(); d.show(4); d.print("hehe"); d.show("hello"); d.print(3.4); } }
结果:
show:4
print:hehe
show:hello
print:3.4
八、静态泛型方法
8.1、静态泛型方法
静态方法不可以访问类上定义的泛型。
如果静态方法访问的类型不确定,可以将泛型定义在方法上
package com.pb.fanxing.demo2; class Tool<T>{ //和类上的泛型一至 public<T> void show(T t){ System.out.println("show:"+t); } //单独的和类上的不一样,但也可以使用类上的 public <Q> void print(Q q){ System.out.println("print:"+q); } //单独的和类上的不一样因为是static的,不能和类上的一样 public static<W> void method(W t){ System.out.println("static:"+t); } } public class GenericStaticDemo { public static void main(String[] args) { //定义字符串 Tool<String> t=new Tool<String>(); //传入字符串 t.show("hehe"); //传入字符串 t.print("dfsds"); //传入double t.print(2323.3); //传入字符串 t.method("ffff"); //传入int t.method(222); } }
结果:
show:hehe print:dfsds print:2323.3 static:ffff static:222
九、泛型接口
9.1、泛型接口
package com.pb.fanxing.demo2; interface Test<T>{ public void show(T t); } class TestImpl<T> implements Test<T>{ @Override public void show(T t) { System.out.println(t); } } public class GenericDemo3 { public static void main(String[] args) { Test<String> test=new TestImpl<String>(); test.show("hello"); Test<Integer> test1=new TestImpl<Integer>(); test1.show(332); } }
十、泛型限定
10.1、泛型限定
使用<?>来占位
package com.pb.fanxing.demo2; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class GenericDemo4 { public static void main(String[] args) { List<String> list=new ArrayList<String>(); list.add("aa"); list.add("ab"); list.add("ac"); List<Integer> list1=new ArrayList<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()); } }*/ //使用泛型T public static<T> void print(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的父类型。下限
package com.pb.fanxing.demo2; import java.util.ArrayList; import java.util.Iterator; class Person{ private String name; private int age; public Person(String name,int age){ this.name=name; this.age=age; } public String getName(){ return name; } public int getAge(){ return age; } } class Student extends Person{ public Student(String name,int age){ super(name,age); } } public class GenericDemo5 { public static void main(String[] args) { ArrayList<Person> a1=new ArrayList<Person>(); a1.add(new Person("abc1",23)); a1.add(new Person("abc2",13)); a1.add(new Person("abc3",33)); ArrayList<Student> a2=new ArrayList<Student>(); a2.add(new Student("abc--1",23)); a2.add(new Student("abc--2",13)); a2.add(new Student("abc--3",33)); print(a1); print(a2); } public static void print(ArrayList<? extends Person> list){//代表Person和Person的子类 Iterator<? extends Person> it=list.iterator(); while(it.hasNext()){ Person p=it.next(); System.out.println(p.getName()+"..."+p.getAge()); } } } //结果 abc1...23 abc2...13 abc3...33 abc--1...23 abc--2...13 abc--3...33
下限
package com.pb.fanxing.demo2; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; class Person{ private String name; private int age; public Person(String name,int age){ this.name=name; this.age=age; } public String getName(){ return name; } public int getAge(){ return age; } } class Student extends Person{ public Student(String name,int age){ super(name,age); } } public class GenericDemo5 { public static void main(String[] args) { TreeSet<Student> ts=new TreeSet<Student>(new MyCompare()); ts.add(new Student("abc--5",23)); ts.add(new Student("abc--2",13)); ts.add(new Student("abc--3",33)); print(ts); } public static void print(Set<? extends Person> list){//代表Person和Person的子类 Iterator<? extends Person> it=list.iterator(); while(it.hasNext()){ Person p=it.next(); System.out.println(p.getName()+"..."+p.getAge()); } } } class MyCompare implements Comparator<Person>{ @Override public int compare(Person p1, Person p2) { return p1.getName().compareTo(p2.getName()); } } //结果: abc--2...13 abc--3...33 abc--5...23