之前Arrays 类中存在sort() 方法, 此方法可以直接对 对象数组进行排序。
1.Comparable接口
可以直接使用java.util.Arrays 类进行数组的排序操作,但对象所在的类必须实现Comparable 接口,用于指定排序接口。
Comparable 接口定义如下:
public interface Comparable<T>{
public int compareTo(T o);
}
此方法返回一个int 类型的数据,但是此int 的值只能是以下三种:
1:表示大于
1:表示小于
0:表示相等
要求:
定义一个学生类,里面有姓名、年龄、成绩三个属性,要求按成绩由高到低排序,如果成绩相等,则按照年龄由低到高排序。
1 class Student implements Comparable<Student> { // 指定类型为Student 2 private String name ; 3 private int age ; 4 private float score ; 5 public Student(String name,int age,float score){ 6 this.name = name ; 7 this.age = age ; 8 this.score = score ; 9 } 10 public String toString(){ 11 return name + "\t\t" + this.age + "\t\t" + this.score ; 12 } 13 public int compareTo(Student stu){ // 覆写compareTo()方法,实现排序规则的应用 14 if(this.score>stu.score){ 15 return -1 ; 16 }else if(this.score<stu.score){ 17 return 1 ; 18 }else{ 19 if(this.age>stu.age){ 20 return 1 ; 21 }else if(this.age<stu.age){ 22 return -1 ; 23 }else{ 24 return 0 ; 25 } 26 } 27 } 28 } 29 public class ComparableDemo01{ 30 public static void main(String args[]){ 31 Student stu[] = {new Student("张三",20,90.0f), 32 new Student("李四",22,90.0f),new Student("王五",20,99.0f), 33 new Student("赵六",20,70.0f),new Student("孙七",22,100.0f)} ; 34 java.util.Arrays.sort(stu) ; // 进行排序操作 35 for(int i=0;i<stu.length;i++){ // 循环输出数组中的内容 36 System.out.println(stu[i]) ; 37 } 38 } 39 }
2.分析比较器的排序原理
实际上比较器的操作,就是经常听到的二叉树的排序算法。通过二叉树进行排序,之后利用中序遍历的方法把内容依次读取出来。
排序的基本原理,使用第一个元素作为根节点,之后如果后面的内容比根节点要大,则放在左子树,如果内容比根节点的内容要大,则放在右子树。
下面就自己手式实现一个二叉树的比较算法。
为了操作方便,此处使用Integer 类完成。
1 public class ComparableDemo02{ 2 public static void main(String args[]){ 3 Comparable com = null ; // 声明一个Comparable接口对象 4 com = 30 ; // 通过Integer为Comparable实例化 5 System.out.println("内容为:" + com) ; // 调用的是toString()方法 6 } 7 };
了解了此特性之后,下面就可以完成一个二叉树算法。
1 class BinaryTree{ 2 class Node{ // 声明一个节点类 3 private Comparable data ; // 保存具体的内容 4 private Node left ; // 保存左子树 5 private Node right ; // 保存右子树 6 public Node(Comparable data){ 7 this.data = data ; 8 } 9 public void addNode(Node newNode){ 10 // 确定是放在左子树还是右子树 11 if(newNode.data.compareTo(this.data)<0){ // 内容小,放在左子树 12 if(this.left==null){ 13 this.left = newNode ; // 直接将新的节点设置成左子树 14 }else{ 15 this.left.addNode(newNode) ; // 继续向下判断 16 } 17 } 18 if(newNode.data.compareTo(this.data)>=0){ // 放在右子树 19 if(this.right==null){ 20 this.right = newNode ; // 没有右子树则将此节点设置成右子树 21 }else{ 22 this.right.addNode(newNode) ; // 继续向下判断 23 } 24 } 25 } 26 public void printNode(){ // 输出的时候采用中序遍历 27 if(this.left!=null){ 28 this.left.printNode() ; // 输出左子树 29 } 30 System.out.print(this.data + "\t") ; 31 if(this.right!=null){ 32 this.right.printNode() ; 33 } 34 } 35 }; 36 private Node root ; // 根元素 37 public void add(Comparable data){ // 加入元素 38 Node newNode = new Node(data) ; // 定义新的节点 39 if(root==null){ // 没有根节点 40 root = newNode ; // 第一个元素作为根节点 41 }else{ 42 root.addNode(newNode) ; // 确定是放在左子树还是放在右子树 43 } 44 } 45 public void print(){ 46 this.root.printNode() ; // 通过根节点输出 47 } 48 }; 49 public class ComparableDemo03{ 50 public static void main(String args[]){ 51 BinaryTree bt = new BinaryTree() ; 52 bt.add(8) ; 53 bt.add(3) ; 54 bt.add(3) ; 55 bt.add(10) ; 56 bt.add(9) ; 57 bt.add(1) ; 58 bt.add(5) ; 59 bt.add(5) ; 60 System.out.println("排序之后的结果:") ; 61 bt.print() ; 62 } 63 };
另一种比较器:Comparator
如果一个类已经开发完成,但是在此类建立的初期并没有实现Comparable接口,此时肯定是无法进行对象排序操作的所以为了解决这样的问题,java又定义了另一个比较器的操作接口——Comparator。
此接口定义在java.util 包中,接口定义如下:
public interface Comparator<T>{
public int compare(T o1, T o2);
boolean equals(Object obj);
}
下面定义一个自己的类,此类没有实现Comparable接口。
1 import java.util.* ; 2 class Student{ // 指定类型为Student 3 private String name ; 4 private int age ; 5 public Student(String name,int age){ 6 this.name = name ; 7 this.age = age ; 8 } 9 public boolean equals(Object obj){ // 覆写equals方法 10 if(this==obj){ 11 return true ; 12 } 13 if(!(obj instanceof Student)){ 14 return false ; 15 } 16 Student stu = (Student) obj ; 17 if(stu.name.equals(this.name)&&stu.age==this.age){ 18 return true ; 19 }else{ 20 return false ; 21 } 22 } 23 public void setName(String name){ 24 this.name = name ; 25 } 26 public void setAge(int age){ 27 this.age = age ; 28 } 29 public String getName(){ 30 return this.name ; 31 } 32 public int getAge(){ 33 return this.age ; 34 } 35 public String toString(){ 36 return name + "\t\t" + this.age ; 37 } 38 }; 39 40 class StudentComparator implements Comparator<Student>{ // 实现比较器 41 // 因为Object类中本身已经有了equals()方法 42 public int compare(Student s1,Student s2){ 43 if(s1.equals(s2)){ 44 return 0 ; 45 }else if(s1.getAge()<s2.getAge()){ // 按年龄比较 46 return 1 ; 47 }else{ 48 return -1 ; 49 } 50 } 51 }; 52 53 public class ComparatorDemo{ 54 public static void main(String args[]){ 55 Student stu[] = {new Student("张三",20), 56 new Student("李四",22),new Student("王五",20), 57 new Student("赵六",20),new Student("孙七",22)} ; 58 java.util.Arrays.sort(stu,new StudentComparator()) ; // 进行排序操作 59 for(int i=0;i<stu.length;i++){ // 循环输出数组中的内容 60 System.out.println(stu[i]) ; 61 } 62 } 63 };
总结:
在使用中尽可以还是作用Comparable 在需要排序的类上实现好此接口,而Comparator 需要单独建立一个排序的类,这样如果有很多的话,则排序的规则类也就会非常多,操作起来比较麻烦。
掌握一点:只要是对象排序,则在javak 永远是以Comparable 接口为准的。
比较器(Comparable、Comparator)类及 二叉树的排序算法,布布扣,bubuko.com