黑马程序员 java基础之TreeSet集合


1_TreeSetDemo

/*
set:无序,元素不重复
<-HashSet:数据结构是哈希表,线程是非同步的
保证元素唯一性的原理:判断元素的hashCode值是否相同
如果相同,还会继续判断元素的equals方法,是否为true.
<-TreeSet:可以对set集合中的元素进行排序,线程是非同步的.
底层数据结构是二叉树(更确切说是红黑树:红黑树的算法特别复杂,以后有时间单独写一篇进行讨论)
保证数据元素唯一性的依据:
compareTo方法.
remove,contains在查找元素过程中需要使用compareTo方法判断.
TreeSet排序的第一种方式:
让元素自身具备比较性,元素需要实现Comparable接口,复写compareTo方法
这种方式叫元素的自然顺序/默认顺序
(排序示意图)
*/
package treeset;
import java.util.*;
class TreeSetDemo{
public static void main(String[] args){
/*
TreeSet ts=new TreeSet();
ts.add("cdef");
ts.add("aaa");
ts.add("bca");
ts.add("Dbcd");
for(Iterator it=ts.iterator();it.hasNext();)
System.out.println(it.next());
*/
/*
String类中实现了Comparable接口,复写了接口中的toCompare方法
使字符串按照字符的ASCII码从小到大排序.
*/
stuMethod();
}
static void stuMethod(){
TreeSet ts=new TreeSet();
ts.add(new Student("zhang",15));
ts.add(new Student("wang",12));
ts.add(new Student("liu",20));
ts.add(new Student("zong",12));//仅年龄相同
ts.add(new Student("liu",20));//姓名年龄均相同
for(Iterator it=ts.iterator();it.hasNext();){
Student stu=(Student)it.next();
System.out.println(stu.getName()+" "+stu.getAge());
}
}
}
//自定义类,向TreeSet集合中存储自定义对象学生,
//希望按照学生的年龄进行排序,当年龄和姓名均相同时,视为同一个人(对象)
//该接口强制让学生具备比较性
//排序时,当主要条件相同时,一定要判断下次要条件
class Student implements Comparable{
private String name;
private int age;
Student(String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
//复写compareTo
public int compareTo(Object obj){
if(!(obj instanceof Student))
throw new RuntimeException("不是Student对象");
Student stu= (Student)obj;
//为了查看怎么排序的
System.out.println(this.name+" "+this.age+
"...compareTo..."+stu.name+" "+stu.age);
if(this.age>stu.age)
return 1;
else
if(this.age==stu.age)//可以在判断条件加上&&this.name==stu.name
//更好的方法,当年龄相同时,对姓名进行排序
return this.name.compareTo(stu.name);
//return 0;
/*
负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
return 0 ,TreeSet认为相同对象,不再存入集合(但第一次,自身与自身比较
个人认为为了判断是否具有可比性,
即使返回0,底层通过某种判断->该集合中没有该元素->加入集合)
)
*/
return -1;
}
}
/*
(API)
当使用TreeSet()构造函数时:
构造一个新的空 set,
该 set 根据其元素的自然顺序进行排序。(字典顺序,数字大小顺序等等)
插入该 set 的所有元素都必须实现 Comparable 接口。
另外,所有这些元素都必须是可互相比较的:对于 set 中的任意两个元素 e1 和 e2,
执行 e1.compareTo(e2) 都不得抛出 ClassCastException。
如果用户试图将违反此约束的元素添加到 set
(例如,用户试图将字符串元素添加到其元素为整数的 set 中),
则 add 调用将抛出 ClassCastException。
*/

 第二种排序方式

/*
TreeSet:
第一种排序方式:
让元素自身具备比较性,元素需要实现Comparable接口,复写compareTo方法
这种方式叫元素的自然顺序/默认顺序
第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的.
(例如我不想按年龄排,按姓名排序,当实现的Comparable
此时代码已封装不能改动)
这时就需要让集合自身具备比较性.
在集合初始化时,就有了比较方式.
当两种方式都存在时,以比较器为主.(根据需要采用不同的比较方式)
定义一个类,实现Comparator接口,覆写compare方法.
*/
package treeset;
import java.util.TreeSet;
import java.util.Comparator;
import java.util.Iterator;
class MyCompare implements Comparator{
public int compare(Object obj_1,Object obj_2){
//利用String类的compareTo方法,此时代码不健壮
//可能出现姓名相同而年龄不同的人->视为不同人
//因此同样判断次要条件->年龄
Student stu_1=(Student)obj_1;
Student stu_2=(Student)obj_2;
int result=stu_1.getName().compareTo(stu_2.getName());
if(result==0){
return stu_1.getAge()-stu_2.getAge();
//或利用Integer封装整数
//return new Integer(stu_1.getAge()).compareTo(stu_2.getAge());
}
return result;
}
}
class TreeSetDemo2{
public static void main(String[] args){
TreeSet ts=new TreeSet(new MyCompare());//该位置传入指定比较器
ts.add(new Student("zhang",15));
ts.add(new Student("wang",12));
ts.add(new Student("liu",20));
ts.add(new Student("zong",14));
ts.add(new Student("zong",12));
for(Iterator it=ts.iterator();it.hasNext();){
Student stu=(Student)it.next();
System.out.println(stu.getName()+" "+stu.getAge());
}
}
}

  TreeSet两种排序方式对比:

/*
两种排序方式对比:
①实现Comparable,复写compareTo:
排序算法和Student类绑定(封装在Student类中),
Student只有一种排序算法并且只能有一种,这是因为
我只能复写一次compareTo.这时,这种方法局限性体现出来了.
②自定义类实现Comparator,复写compare:
之所以提供比较器排序接口,
是因为有时需要对同一对象进行多种不同方式的排序,
这点自然排序Comparable不能实现。
另外,Comparator 接口的一个好处是将比较排序算法和实体类分离了(而不再其内部),更加灵活。
、TreeSet():根据TreeSet中元素实现的 Comparable 接口的 compareTo 方法比较排序
、TreeSet(Comparator comparator):根据给定的 comparator 比较器,对 TreeSet 中的元素比较排序
*/

  Comparator简单练习:

/*
按照字符串长度排序
return s1.length()-s2.length();
字符串本身具备比较性,它的比较方式不是所需要的.
这时只能采用实现Comparator
*/
package treeset;
import java.util.*;
class StringLenCom implements Comparator{
public int compare(Object obj_1,Object obj_2){
String str_1=(String)obj_1;
String str_2=(String)obj_2;
int num=str_1.length()-str_2.length();
System.out.println(str_1+"...compare..."+str_2+" "+num);
if(num==0){//两个字符串相同,不处理,认为相同对象,不再存入集合
return str_1.compareTo(str_2);
}
return num;
}
}
class TreeSetTest{
public static void main(String[] args){
TreeSet ts=new TreeSet(new StringLenCom());
ts.add("a");
ts.add("bc");
ts.add("de");
ts.add("c");
ts.add("d");
ts.add("f");
for(Iterator it = ts.iterator();it.hasNext(); ){
System.out.println(it.next());
}
}
}
/*
在写排序算法时,注意重复元素处理!
*/

  

posted @ 2013-05-14 21:10  xiewen3410  阅读(134)  评论(0编辑  收藏  举报