Java比较器

当我们要对一组数字进行排序的时候,可以写一个排序算法实现;如果要对字母进行排序的时候,则通过26个字母的自然顺序进行排序。

但是,当需要排序的集合或数组不是单纯的数字类型时,我们通常使用ComparatorComparable,以简单的方式实现对象排序或自定义排序。


1.Comparable内部比较器,此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo 方法被称为它的自然比较方法。


2.Comparator外部比较器,是T - 此 Comparator 可以比较的对象类型,它是强行对某个对象collection 进行整体排序 的比较函数。


3.区别:
Comparable 用作默认的比较方式 。
Comparator 用作自定义的比较方式,当默认的比较方式不适用时或者没有提供默认的比较方式,使用Comparator就非常有用。
Comparator 强行对某个对象collection进行整体排序的比较函数,可以将Comparator传递给Collections.sortArrays.sort
Comparable强行对实现它的每个类的对象进行整体排序,实现此接口的对象列表(和数组)可以通过Collections.sorArrays.sort进行自动排序。


4.用法:

1、内部比较器:java.lang.Comparable<T> 接口声明了:int compareTo(T o) 方法 
  比较此对象与执行对象的顺序。比较规则同上,即: 
  1)如果此对象大于指定对象,返回正整数 ;
  2)如果此对象小于指定对象,返回负整数 ;
  3)如果此对象等于指定对象,返回零 。


2、外部比较器:java.util.Comparator<T> 接口声明了: int compare<T o1, T o2> 方法 
  比较用来排序的两个参数: 
  1)如果o1大于o2,则返回正整数; 
  2)如果o1小于o2,则返回负整数 ;
  3)如果o1等于o2,则返回零 。


这里我们使用TreeSet来举例说明:

1.先定义一个学生类:在学生类实现内部比较器Comparable)接口,我们需要重写int compareTo(T o) 方法。这里我们是对学生成绩排序。double是基本数据类型,这里我们操作的是对象,需要对double进行装箱。

public class Student implements Comparable<Student> {
	String name;// 姓名
	int age;// 年龄
	double score;// 成绩

	public Student() {
	}

	public Student(String name, int age, double score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}

	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}

	@Override
	public int compareTo(Student o) {
		Double double1 = new Double(this.score);
		Double double2 = new Double(o.getScore());
		return double1.compareTo(double2);
	}
}

调用方法;

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

public class Test01 {
	public static void main(String[] args) {
		Student stu1 = new Student("一大大", 20, 88.5);
		Student stu2 = new Student("二大大", 21, 88);
		Student stu3 = new Student("三大大", 18, 89);
		//1.内部比较器  eg:成绩排序
		TreeSet<Student> treeSet1 = new TreeSet<Student>();
		treeSet1.add(stu1);
		treeSet1.add(stu2);
		treeSet1.add(stu3);
		showStudent(treeSet1);
	}
	public static void showStudent(TreeSet<Student> students) {
		for (Student student : students) {
			System.out.println(student);
		}
	}
}

输出结果:

Student [name=二大大, age=21, score=88.0]
Student [name=一大大, age=20, score=88.5]
Student [name=三大大, age=18, score=89.0]


2.使用外部比较器Comparator)来实现:先定义一个外部比较器的方法来实现接口Comparator,重写 int compare<T o1, T o2> 方法 ,这里我们来比较年龄。

class ageComp implements Comparator<Student> {

	@Override
	public int compare(Student o1, Student o2) {
		return o1.age - o2.age;
	}
}
调用方法:

//2.外部比较器 eg:年龄排序
		Comparator<Student> comparator = new ageComp();
		TreeSet<Student> treeSet2 = new TreeSet<>(comparator);
		treeSet2.add(stu1);
		treeSet2.add(stu2);
		treeSet2.add(stu3);
		showStudent(treeSet2);


输出结果:

Student [name=三大大, age=18, score=89.0]
Student [name=一大大, age=20, score=88.5]
Student [name=二大大, age=21, score=88.0]


3.当然,我们还可以用匿名内部类来写Comparator:这里我们来按名字排序。

		//3.外部比较器内部类 eg:姓名排序
		TreeSet<Student> treeSet3 = new TreeSet<>(new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				return o1.name.compareTo(o2.name);
			}
		});
		treeSet3.add(stu1);
		treeSet3.add(stu2);
		treeSet3.add(stu3);
		showStudent(treeSet3);
输出结果:

Student [name=一大大, age=20, score=88.5]
Student [name=三大大, age=18, score=89.0]
Student [name=二大大, age=21, score=88.0]


最后,总结一下两种比较器的区别: 
1)如果使用内部比较器,需要比较的对象必须要实现Comparable接口,并重写compareTo( T o)方法,否则不能直接使用Collections中的sort方法,程序会报错。因为程序不知道你要以何种方式来进行比较。 
2)使用外部比较器,需要自己写一个比较器实现Comparator接口,并实现compare(T o1, T o2)方法,根据自己的需求定义比较规则。使用外部比较器这种方式比较灵活。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值