黑马程序员技术交流社区
标题:
TreeSet排序问题
[打印本页]
作者:
ぺsimon☆
时间:
2013-4-25 15:05
标题:
TreeSet排序问题
/*
这是关于TreeSet的功能演示.
需求:向TreeSet集合存入Student学生对象,并按照年龄进行排序
*/
import java.util.*;
class Student implements Comparable //创建学生类并实现Comparable类
{
private String name;
private int age;
Student(String name,int age) //构造函数初始化
{
this.name=name;
this.age=age;
}
public String getName() //定义获取姓名的函数
{
return this.name;
}
public int getAge() //定义获取年龄的函数
{
return this.age;
}
public void setName(String name) //定义改变姓名的函数
{
this.name=name;
}
public void setAge(int age) //定义改变年龄的函数
{
this.age=age;
}
public int compareTo(Object obj) //复写compareTo方法
{
if(!(obj instanceof Student))
throw new RuntimeException(); //抛出RuntimeException异常
Student s=(Student)obj;
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);
}
return -1;
}
}
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet(); //创建容器
ts.add(new Student("xiaochen01",31));
ts.add(new Student("xiaochen01",31));
ts.add(new Student("xiaochen02",32));
ts.add(new Student("xiaochen03",33));
ts.add(new Student("xiaochen04",34));
ts.add(new Student("xiaochen05",30));
ts.add(new Student("xiaochen06",30));
Iterator it=ts.iterator(); //获取迭代器
//遍历并输出容器中的数据
while(it.hasNext())
{
Student s=(Student)it.next();
sop(s.getName()+"......"+s.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
复制代码
问题1:为什么要实现Coparrable类呢?现在自己写的compareTo方法已经可以比较两个数的大小了
问题2:
运行结果如下: 为什么xiaochen04进来之后不用跟xiaochen01比较大小呢?
xiaochen01...compareTO...xiaochen01
xiaochen02...compareTO...xiaochen01
xiaochen03...compareTO...xiaochen01
xiaochen03...compareTO...xiaochen02
xiaochen04...compareTO...xiaochen02
xiaochen04...compareTO...xiaochen03
xiaochen05...compareTO...xiaochen02
xiaochen05...compareTO...xiaochen01
xiaochen06...compareTO...xiaochen02
xiaochen06...compareTO...xiaochen01
xiaochen06...compareTO...xiaochen05
xiaochen05......30
xiaochen06......30
xiaochen01......31
xiaochen02......32
xiaochen03......33
xiaochen04......34
作者:
袁梦希
时间:
2013-4-25 15:19
楼主你好,这是我自己的总结,你可以看看!
TreeSet第一种排序方式:
往TreeSet集合里面存对象,并没有把排序的方式告诉集合
,所以往TreeSet集合里存的对象必须具备比较性。
实现Comparable接口,实现整体排序,这种排序被称为类的
自然排序.类的CompareTo方法被称为自然比较方法.
在比较的时候,第一先数据先进来,然后第二个再进来,第二
个数据调用自己的CompareTo方法与第一先进来的数据进行
比较,
返回int类型,返回0,此类对象与指定对象相等,所以不存
。
比如Student对象中,只有年龄相同就不存了,那么就错了
,年龄相同之后还要判断名字相同,都相同以后才视为同一
个人,所以不存。也就是说:当主要条件相等时,要对次要
条件进行排序。
如果按对象的降序排列(盲点)
因为name是字符串类型,所以查找String对应的API中有对
应的compareTo方法,用他来对name进行排序也就是String
类已经实现了Comparable接口了。是按字典顺序排序
为了效率,TreeSet底层利用二叉树原理。
也就是说返回负数往左边放,正数放在右边,0不存的原理
减少比较次数就提高了效率。左中右的方式取出数据.
如果想往TreeSet集合里怎么存的就怎么取出来,怎么办?
只要在compareTo方法中返回1,并且以二叉树的顺序取出。
保证元素唯一性的依据是compareTo返回0.
====================================================
TreeSet第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要
的,这时就需要让集合自身具备比较性。
我举个例子:比如说,可以拿集合作为参照物,拿两个元素
跟这个参照物进行比较,如果比这个物体小就放左,比这个
物体大就放右面。就好比一个刻度板。
集合一初始化就有比较方式,参与构造函数。
而第一种方式是拿Student对象中的元素来一个比较一个,
来一个比较一个。
在Student对象中,如果想按照姓名排序,就不能改代码了
。那么怎么实现呢。
首先,实现Comparator接口,然后重写compare,传两个参
数进行比较,不用重新ecquls()方法了,因为实现类已经重
写了。
当两种排序都存在时,以比较器为主。
作者:
谭威
时间:
2013-4-25 15:19
你不实现 Comparable接口,能有compareTo方法吗。实现一个接口,必须要实现接口中的方法。
你的Student实现了 Comparable接口。就必须重写compareTo方法,在这个方法中根据Student特有的属性age来比较。如果你不实现Comparable,自己在Student中定义compareTo方法是没有任何意义的。
作者:
谭威
时间:
2013-4-25 15:24
第二个问题。2先和1比较了,2比1大,4再和2比较,4比2也大,4根本就不需要和1比较了
作者:
刘胜寒
时间:
2013-4-25 15:29
估计跟TreeSet的底层数据结构有关。。。
二叉树的结果是节点左边小于节点节点右边大于节点
当你进行比较的时候。。。
第一次跟根节点比较如果相同则停止比较..
如果小于根节点就去左子树进行比较,则不比较右子树的所有节点。否则相反。
如果当前节点的值小于要比较的对象,并且左子树为null,那么则把要比较的对象放在当前节点的左子树上,并结束;
如果当前节点的值大于要比较的对象,并且右子树为null,那么则把要比较的对象放在当前节点的右子树上,并结束;
一层一层的递归比较。。。
我感觉是这样的。。
这样做很节省时间平均只要话费log(n)次的查找就能却确定位置
作者:
黄玉昆
时间:
2013-4-26 23:39
如果仍有问题,请继续追问,如果问题已解决,请将分类改为已解决,谢谢
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2