比较器
在之前接触过了Arrays类,那么下面来观察在Arrays类之中存在的一个方法:
- 对象数组排序:public static void sort(Object[] a);
范例:实现排序
package cn.mldn.demo;
import java.util.Arrays;
class Person{
private String name;
private int age;
public Person(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ", 年龄:" + this.age;
}
}
public class TextDemo {
public static void main(String[] args) throws Exception {
Person per[] = new Person[]{new Person("张三",19),
new Person("李四",20),new Person("王五",21)};
Arrays.sort(per); //排序
for(int x = 0 ; x < per.length; x++){
System.out.println(per[x]);
}
}
}
结果:Exception in thread "main" java.lang.ClassCastException: cn.mldn.demo.Person cannot be cast to java.lang.Comparable
此时需要让Person类实现Comparable接口,而这就是一个比较器
Comparable接口
java.lang.Comparable 接口是一个最为常用的比较器 那么此接口定义如下:
public interface Comparable<T> public int compareTo(T o) |
在Comparable接口之中发现只有一个compareTo()方法,而此方法可以返回三种类型的:-1(小),0(等于),1(大于)。
范例:使用比较器
package cn.mldn.demo;
import java.util.Arrays;
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ", 年龄:" + this.age;
}
@Override
public int compareTo(Person o){
if(this.age > o.age){
return 1;
} else if (this.age < o.age){
return -1;
}
return 0;
}
}
public class TextDemo {
public static void main(String[] args) throws Exception {
Person per[] = new Person[]{new Person("张三",19),
new Person("李四",20),new Person("王五",21)};
Arrays.sort(per); //排序
for(int x = 0 ; x < per.length; x++){
System.out.println(per[x]);
}
}
}
结果:姓名:张三, 年龄:19
姓名:李四, 年龄:20
姓名:王五, 年龄:21
Binary Tree
既然已经知道了对象之间的大小比较操作,那么就可以利用此概念实现二叉树开发,二叉树基本原则如下:
- 一个节点下可以保存两个节点,分别称为左子树和右子树;
- 取第一个数据作为根节点,比根节点小的数据要放在左子树上,比根节点大的数据要放在右子树上
- 在进行输出的时候按照中序遍历(左-中-右)进行数据的取出。
范例:下面利用 Comparable实现二叉树操作
- 大小关系利用Comparable接口的compareTo()方法实现
package cn.mldn.test;
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ", 年龄:" + this.age;
}
@Override
public int compareTo(Person o){
if(this.age > o.age){
return 1;
} else if (this.age < o.age){
return -1;
}
return 0;
}
}
@SuppressWarnings("rawtypes")
class BinaryTree{
private class Node{ //一定要存在节点类
private Comparable data; //必须排序的是Comparable接口对象
private Node left; //左子树
private Node right; //右子树
public Node(Comparable data){
this.data = data;
}
@SuppressWarnings("unchecked")
public void addNode(Node newNode){
if(this.data.compareTo(newNode.data) < 0){
if(this.left == null){
this.left = newNode;
}else {
this.left.addNode(newNode);
}
}else{
if(this.right == null){
this.right = newNode;
}else{
this.right.addNode(newNode);
}
}
}
public void toArrayNode(){
if(this.left != null){ //左子树
this.left.toArrayNode();
}
BinaryTree.this.retData[BinaryTree.this.foot++] = this.data;
if (this.right != null){
this.right.toArrayNode();
}
}
}
private Node root; //根节点
private int count; //统计对象的保存个数
private int foot; //操作脚标
private Object[] retData;
public void add(Comparable data){
if(data == null){
return;
}
Node newNode = new Node(data); //将新的数据变为一个节点
if(this.root == null){ //根节点没有数据
this.root = newNode; //新的节点将作为根节点存在
}else { //要保存在合适的节点中
this.root.addNode(newNode);
}
this.count ++; //保存个数加一
}
public Object[] toArray(){
if(this.root == null){
return null;
}
this.foot = 0;
this.retData = new Object[this.count]; //以保存大小开辟数组
this.root.toArrayNode();
return this.retData;
}
}
public class BinaryTreeDemo {
public static void main(String[] args){
BinaryTree bt = new BinaryTree();
bt.add(new Person("张三",20));
bt.add(new Person("李四",25));
bt.add(new Person("王五",28));
Object[] data = bt.toArray();
for (int x = 0; x < data.length; x++){
System.out.println(data[x]);
}
}
}
结果:姓名:王五, 年龄:28
姓名:李四, 年龄:25
姓名:张三, 年龄:20
此程序只作为了解,以后工作不会这样写
挽救的比较器:Comparator
在工作之中如果使用到比较器,肯定首选的是Comparable,但是Comparable有一个特点,它必须在一个类定义的时候就实现好接口,可是如果有这样一种情况,一个类已经开发完成了,并且此类不允许再做出任何修改,此类在先前设计的时候没有考虑对象数组的排序问题,后期又提出了此问题。但是代码已经不能变更,那么这个时候如何排序呢
范例:开发好的类
class Person {
private String name;
private int age;
public Person(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ", 年龄:" + this.age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
Person类已经开发完成,并且交给客户使用了,但是后来需要进行对象数组排序,那么这个时候由于Person类无法修改了,那么只能采用另外一种比较器:java.util.Comparator接口,此接口定义如下
public interface Comparator<T>{ public int compare(T o1, T o2); public boolean equals(Object obj); } |
范例:定义专门的比较器
class PersonComparator implements Comparator<T>{
public int compare(Person o1, Person o2){
if(o1.getAge() > o2.getAge()){
return -1;
}else if(o1.getAge() < o2.getAge()){
return 1;
}
return 0;
}
}
此类只能够为Person类服务。随后如果要排序在Arrays类有如下一个方法
- 排序:public static<T> void sort(T[] a, Comparatir<? super T> c)
package cn.mldn.demo;
import java.util.Comparator;
import java.util.Arrays;
class Person {
private String name;
private int age;
public Person(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ", 年龄:" + this.age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
class PersonComparator implements Comparator<Person>{
public int compare(Person o1, Person o2){
if(o1.getAge() > o2.getAge()){
return -1;
}else if(o1.getAge() < o2.getAge()){
return 1;
}
return 0;
}
}
public class TextDemo {
public static void main(String[] args) throws Exception {
Person per[] = new Person[]{new Person("张三",19),
new Person("李四",20),new Person("王五",21)};
Arrays.sort(per,new PersonComparator()); //排序
for(int x = 0 ; x < per.length; x++){
System.out.println(per[x]);
}
}
}
两种比较器的区别
- 如果对象数组要进行排序,则需要使用到比较器,Jaya提供有两种比较器:Comparable、Comparator;
- java lang Comparable是在一个类定义的时候实现的接口,里面有一个compareTo()方法;
- java.util.Comparator 是一个挽救的比较器接口,需要单独为需要比较的类定义一个新的比较规则类,里面有两个方法:compare()、equals()。