由TreeSet引出的Comparable和Comparator学习小结

本文介绍了Java中TreeSet的两种排序方式:元素自然顺序排序及自定义比较器排序,并通过实例展示了如何按照不同属性对学生对象进行排序。


 

TreeSet

可以对Set集合中的元算进行排序,底层数据结构是二叉树,保证元素唯一性的依据是compareto方法返回0

          

TreeSet第一种排序方式:

让元素自身具备比较性,元素需要实现comparable接口,覆盖compareto方法,这种方式也称为元素的自然顺序,或者叫做默认顺序。

          例子:往TreeSet集合中存储自定义对象学生,想按照学生的年龄进行排序。(升序)

 

import java.util.Iterator;
import java.util.TreeSet;

/**Tree小练习,自定义排序规则
 * @author Administrator
 */
public class TreeSetDemo {

	public static void main(String[] args) {

		TreeSet<Student> ts = new TreeSet<Student>();
		ts.add(new Student("a",35));
		ts.add(new Student("z",10));
		ts.add(new Student("z",10));//重复项,被过滤掉
		ts.add(new Student("c",20));
		ts.add(new Student("aa",24));
		ts.add(new Student("a",40));
		Iterator<Student> it = ts.iterator();
		while(it.hasNext()){
			Student s = it.next();
			System.out.println(s.getName()+":"+s.getAge());
		}
	}

}

/**
 * 实现Comparable接口,让元素自身具有比较性
 * @author Administrator
 *
 */
class Student implements Comparable{
	private String name;
	private int age;
	public Student(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;
	}
	
	/**自定义排序,按照年龄排序
	 * @return int 
	 * 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
	 */
	@Override
	public int compareTo(Object o) {
		if (!(o instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student) o;
//		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;
		
//		return -1; //这种方式按照插入顺序取出元素,而且是可以有重复元算
	}
	
	public String toString() {
		return name+age;
	}
	
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		System.out.println("这个刚发根本不会调用");
		return super.equals(obj);
	}
	
}


 

TreeSet第二种排序方式:

当元素自身不具备比较性,或者具备的比较性不是所需要的。这里就需要让集合自身具备比较性。在集合初始化时就有了比较方式。实现方式就是自定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

          例子:以前是按照学生的年龄排序,现在想按照姓名排序,在不该变学生类的前提下。Student类还使用上面的那个。

 

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**当元素自身不具备比较性,或者具备的比较性不是所需要的。
 * 这是就需要让集合自身具备比较性。在集合初始化时就有了比较方式。
 * 这就需要自定义比较器:定义一个类,实现comparator接口,覆盖compare方法
 * @author Administrator
 *
 */
public class TreeSetDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TreeSet<Student> ts = new TreeSet<Student>(new MyCompare());
		ts.add(new Student("a",35));
		ts.add(new Student("z",10));
		ts.add(new Student("z",10));//重复项,被过滤掉
		ts.add(new Student("c",20));
		ts.add(new Student("aa",24));
		ts.add(new Student("a",40));
		Iterator it = ts.iterator();
		while(it.hasNext()){
			Student s = (Student) it.next();
			System.out.println(s.getName()+":"+s.getAge());
		}
	}

}

/**
 * 自己的比较器
 * @author Administrator
 *
 */
class MyCompare implements Comparator{

	/**按照姓名排序,
	 * @return int
	 * 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
	 */
	@Override
	public int compare(Object o1, Object o2) {
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
//		return s1.getName().compareTo(s2.getName());//按照姓名
		
		int num =  s1.getName().compareTo(s2.getName());
		if(num == 0){
//			return s1.getAge()- s2.getAge();
			
			/*
			if(s1.getAge() > s2.getAge())
				return 1;
			if(s1.getAge() == s2.getAge())
				return 0;
			return -1;
			*/
			
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return num ;
	}
	
}


 

注意;排序时,当主要条件相同时,一定要判断次要条件。当两种排序都存在时以比较器为主。

 

Comparator可以看成一种将算法和数据分离,开发中推荐使用

Comparator也可以在下面两种环境下使用:
1
、原类定义时没有实现Comparable,无法自动排序的,可以通过Comparator来实现排序而不必改变对象本身
2
、需要使用多种排序标准的,比如升序、降序、按照某些特定规则排序等。

 

最后提一下:如果是用数组存储元素可以使用Arrays.sort()进行自动排序,因为本例是学习TreeSet,所以没有给出例子。

static

<T> void

sort(T[] a,Comparator<? super T> c)
          
根据指定比较器产生的顺序对指定对象数组进行排序。

static

<T> void

sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
          
根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值