一、Comparable接口
可以直接使用java.util.Arrays类进行数组的排序操作,但对象所在的类必须实现Comparable接口,用于指定排序接口。
Comparable接口定义如下:
public interface Comparable<T>{
public int compareTo(T o);
}
此方法返回一个int类型的数据,但是此int的值只能是一下三种:
1:表示大于
-1:表示小于
0:表示相等
样例:
public class Student implements Comparable<Student>{ //指定类型为Student
private String name;
private int age;
private float score;
public Student(String name, int age, float score){
this.name = name;
this.age = age;
this.score = score;
}
public String toString(){
return this.name + "\t\t" + this.age + "\t\t" + this.score;
}
public int compareTo(Student stu){ //覆写compareTo()方法,实现排序规则的应用
if(this.score > stu.score){
return 1;
}else if(this.score < stu.score){
return -1;
}else{
if(this.age > stu.age){
return 1;
}else if(this.age < stu.age){
return -1;
}else{
return 0;
}
}
}
public static void main(String[] args){
Student[] stu = {new Student("张三", 20, 90.0f), new Student("李四", 27, 99.0f),
new Student("王五", 22, 70.0f), new Student("赵六", 30, 100.0f)};
java.util.Arrays.sort(stu); //进行排序操作
for(int i = 0; i < stu.length; i++){ //循环输出数组中的内容
System.out.println(stu[i]);
}
}
}
注意:如果在Student类中没有实现Comparable接口,则在执行时会出现一下的异常
Exception in thread "main" java.lang.ClassCastException;
二、比较器的排序原理
二叉树的排序方法,通过二叉树进行排序,之后利用中序遍历的方式把内容一次读取出来。
二叉树排序的基本原理就是,将第一个内容作为根节点保存,之后如果后面的值比根节点的值小,则放在根节点的左子树上,如果后面的值比根节点的值大,则放在根节点的右子树。
public class BinaryTree{
class Node{ //声明一个节点类
private Comparable data; //保存具体的内容
private Node left; //保存左子树
private Node right; //保存右子树
public Node(Comparable data){
this.data = data;
}
public void addNode(Node newNode){
//确定是放在左子树还是右子树
if(newNode.data.compareTo(this.data) < 0){ //内容小,放在左子树
if(this.left == null){
this.left = newNode; //直接将新的节点设置成左子树
}else{
this.left.addNode(newNode); //继续向下判断
}
}
if(newNode.data.compareTo(this.data) >= 0){
if(this.right == null){
this.right = newNode;
}else{
this.right.addNode(newNode);
}
}
}
public void printNode(){ //输出的时候采用中序遍历
if(this.left != null){
this.left.printNode(); //输出左子树
}
System.out.print(this.data + "\t");
if(this.right != null){
this.right.printNode();
}
}
}
private Node root; //根元素
public void add(Comparable data){ //加入元素
Node newNode = new Node(data);
if(root == null){ //没有根节点
root = newNode; //第一个元素作为根节点
}else{
root.addNode(newNode); //确定是放在左子树还是放在右子树
}
}
public void print(){
this.root.printNode(); //通过根节点输出
}
public static void main(String[] args){
BinaryTree bt = new BinaryTree();
bt.add(8);
bt.add(3);
bt.add(3);
bt.add(10);
bt.add(9);
bt.add(1);
bt.add(5);
bt.add(5);
System.out.println("排序后的结果:");
bt.print();
}
}
三、Comparator接口
如果一个类已经开发完成,但是在此类建立的初期并没有实现Comparable接口,此时肯定是无法进行对象排序操作的,所以为了解决这样的问题,java中定义了另一个比较器的操作接口----Comparator。此接口定义在java.util包中,接口定义如下:
public interface Comparator<T>{
public int compare(T o1, T o2);
boolean equals(Object obj);
}
import java.util.* ;
class Student{ // 指定类型为Student
private String name ;
private int age ;
public Student(String name,int age){
this.name = name ;
this.age = age ;
}
public boolean equals(Object obj){ // 覆写equals方法
if(this==obj){
return true ;
}
if(!(obj instanceof Student)){
return false ;
}
Student stu = (Student) obj ;
if(stu.name.equals(this.name)&&stu.age==this.age){
return true ;
}else{
return false ;
}
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
public String toString(){
return name + "\t\t" + this.age ;
}
};
class StudentComparator implements Comparator<Student>{ // 实现比较器
// 因为Object类中本身已经有了equals()方法
public int compare(Student s1,Student s2){
if(s1.equals(s2)){
return 0 ;
}else if(s1.getAge()<s2.getAge()){ // 按年龄比较
return 1 ;
}else{
return -1 ;
}
}
};
public class ComparatorDemo{
public static void main(String args[]){
Student stu[] = {new Student("张三",20),
new Student("李四",22),new Student("王五",20),
new Student("赵六",20),new Student("孙七",22)} ;
java.util.Arrays.sort(stu,new StudentComparator()) ; // 进行排序操作
for(int i=0;i<stu.length;i++){ // 循环输出数组中的内容
System.out.println(stu[i]) ;
}
}
};
总结:
Comparator和Comparable的区别如下:
1.Comparable用在对象本身,说明这个对象是可以被比较的,也就是说可以被排序的。(String和Integer之所以可以比较大小,是因为它们都实现了Comparable接口,并实现了compareTo()方法)。
2.Comparator用在对象外面,相当于定义了一套排序算法来排序。