zoukankan      html  css  js  c++  java
  • 通过策略模式认识comparable接口与comparator接口

      comparable接口只是一个引子,引出策略模式中的接口comparator接口

      comparable接口的演变思想还是有价值去研究的

    一.comparable接口演变

    演变一:

      这一版本中运用选择排序实现了一个int类型最基本的排序功能

     1 public class Sorter {
     2 
     3     public static void sort(int[] arr) {
     4         for (int i=0; i<arr.length - 1; i++){
     5             int minPoint = i;
     6 
     7             for(int j=i+1; j<arr.length; j++){
     8                 minPoint = arr[j] < arr[minPoint] ? j : minPoint;
     9             }
    10 
    11             swap(arr, i, minPoint);
    12         }
    13     }
    14 
    15     static void swap(int[] arr, int i , int j){
    16         int temp = arr[i];
    17         arr[i] = arr[j];
    18         arr[j] = temp;
    19     }
    20 }
    1 public class Main {
    2     public static void main(String[] args) {
    3         int[] a = {9,2,3,5,7,1,4};
    4         Sorter sorter = new Sorter();
    5         sorter.sort(a);
    6         System.out.println(Arrays.toString(a));
    7     }
    8 }

      问一:如果要对float类型的数字进行排序怎么办?对double类型、byte类型呢?

        答:只需要在Sorter类中重写sort方法就能实现

      问二:如果要对一些引用数据类型进行排序呢?

        答:这一版本肯定是不行的

    演变二:

      接问题二进而有了第二个版本,针对引用数据类型进行排序,我们这里举例Cat

      那么怎么比较猫的大小呢?这里就需要我们编写方法规定好比较规则了(CompareTo方法)

     1 public class Cat {
     2     int weight,height;
     3 
     4     public Cat(int weight,int height){
     5         this.weight = weight;
     6         this.height = height;
     7     }
     8 
     9     public int compareTo(Cat cat){
    10         if (this.weight < cat.weight) return -1;
    11         else if(this.weight > cat.weight) return 1;
    12         else return 0;
    13     }
    14 
    15     @Override
    16     public String toString() {
    17         return "Cat{" +
    18                 "weight=" + weight +
    19                 ", height=" + height +
    20                 '}';
    21     }
    22 }
     1 public class Sorter {
     2 
     3     public static void sort(Cat[] arr) {
     4         for (int i=0; i<arr.length - 1; i++){
     5             int minPoint = i;
     6 
     7             for(int j=i+1; j<arr.length; j++){
     8                 minPoint = arr[j].compareTo( arr[minPoint] ) == -1 ? j : minPoint;
     9             }
    10             swap(arr, i, minPoint);
    11         }
    12     }
    13 
    14     static void swap(Cat[] arr, int i , int j){
    15         Cat temp = arr[i];
    16         arr[i] = arr[j];
    17         arr[j] = temp;
    18     }
    19 }
    1 public class Main {
    2     public static void main(String[] args) {
    3         Cat[] cat = {new Cat(3,3), new Cat(5,5), new Cat(1,1)};
    4         Sorter sorter = new Sorter();
    5         sorter.sort(cat);
    6         System.out.println(Arrays.toString(cat));
    7     }
    8 }

      问三:这个版本中我们对Cat类进行了排序,那么如果我要对Dog类、Egg类进行排序怎么办?

        答:我们可以将Sorter类中传入sort方法的参数类型设置为Object类型

      问四:解决了上面问三,但是Object类中并没有compareTo方法怎么办?

        答:可以新建一个接口,里面定义compareTo方法,所有参与比较的类都要实现该接口

    演变三:

      解决问三、问四问题

    1 public interface Comparable {
    2     //为了实现多个类共用此方法,这里将传入参数设置为Object类型
    3     public int compareTo(Object o);
    4 }
     1 public class Sorter {
     2     //为了实现共用,而将传入参数设置为Comparable
     3     public static void sort(Comparable[] arr) {
     4         for (int i=0; i<arr.length - 1; i++){
     5             int minPoint = i;
     6 
     7             for(int j=i+1; j<arr.length; j++){
     8                 minPoint = arr[j].compareTo( arr[minPoint] ) == -1 ? j : minPoint;
     9             }
    10             swap(arr, i, minPoint);
    11         }
    12     }
    13 
    14     static void swap(Comparable[] arr, int i , int j){
    15         Comparable temp = arr[i];
    16         arr[i] = arr[j];
    17         arr[j] = temp;
    18     }
    19 }
     1 public class Dog implements Comparable {
     2 
     3     int food;
     4 
     5     public Dog(int food){
     6         this.food = food;
     7     }
     8 
     9     //这里传入参数为Object类型
    10     @Override
    11     public int compareTo(Object o) {
    12         //这里要使用Dog类型进行转换时,需要将Object类型的参数转换为Dog类型
    13         Dog dog = (Dog)o;
    14         if (this.food<dog.food) return -1;
    15         else if (this.food<dog.food) return 1;
    16         else return 0;
    17     }
    18 
    19     @Override
    20     public String toString() {
    21         return "Dog{" +
    22                 "food=" + food +
    23                 '}';
    24     }
    25 }
     1 public class Cat implements Comparable{
     2     int weight,height;
     3 
     4     public Cat(int weight,int height){
     5         this.weight = weight;
     6         this.height = height;
     7     }
     8 
     9     //这里传入参数为Object类型
    10     public int compareTo(Object o){
    11         //这里要使用Cat类型进行转换时,需要将Object类型的参数转换为Cat类型
    12         Cat cat = (Cat)o;
    13         if (this.weight < cat.weight) return -1;
    14         else if(this.weight > cat.weight) return 1;
    15         else return 0;
    16     }
    17 
    18     @Override
    19     public String toString() {
    20         return "Cat{" +
    21                 "weight=" + weight +
    22                 ", height=" + height +
    23                 '}';
    24     }
    25 }
    1 public class Main {
    2     public static void main(String[] args) {
    3         Dog[] dogs = {new Dog(3), new Dog(5), new Dog(1)};
    4         Sorter sorter = new Sorter();
    5         sorter.sort(dogs);
    6         System.out.println(Arrays.toString(dogs));
    7     }
    8 }

      问五:如果比较对象与被比较对象类型不相同,那么传入参数进行强制转换时就会报错

        答:利用java中泛型在演变三基础上进行修改

    演变四:

      在上一个版本基础上利用泛型进行代码修改

      仅展示部分修改后代码,未修改的部分参照演变三中代码

    1 //加上泛型,更加灵活
    2 public interface Comparable<T> {
    3     //不必设置为Object类型
    4     public int compareTo(T o);
    5 }
     1 //实现接口时传入泛型
     2 public class Dog implements Comparable<Dog> {
     3 
     4     int food;
     5 
     6     public Dog(int food){
     7         this.food = food;
     8     }
     9 
    10     //实现接口中方法,将传入参数确定比较类型
    11     @Override
    12     public int compareTo(Dog dog) {
    13         //增加泛型后这里减少了强制转换带来的隐患
    14         if (this.food<dog.food) return -1;
    15         else if (this.food<dog.food) return 1;
    16         else return 0;
    17     }
    18 
    19     @Override
    20     public String toString() {
    21         return "Dog{" +
    22                 "food=" + food +
    23                 '}';
    24     }
    25 }

    演变五:

      最完美的结果就是实现java中自带的comparable接口

    二.comparator接口

      接着上面comparable接口,在猫这个实体类在comparable接口中的比较策略是通过比较体重来进行判断的。但是,实际生活中比较猫可以通过很多方面,如体重、身高、身长等。那么怎样实现猫比较大小的策略可以灵活指定呢?

      这里在解决上述问题时将原本的一个泛型变为两个泛型,第一个泛型为比较的数组,第二个泛型为打比较的策略。如果需要添加新的比较策略,只需在新建类中定义具体比较策略并实现相应接口,在需要调用时利用多态new出不同实现类即可实现不同方式的比较策略

    1 public interface Comparator<T> {
    2     //定义两个泛型,第一个为比较数组,第二个为比较策略
    3     public int compare(T o1,T o2);
    4 }
     1 /**
     2  * 狗的比较器
     3  * 具体实现类,定义狗的具体比较策略
     4  */
     5 public class DogComparator implements Comparator<Dog> {
     6     @Override
     7     public int compare(Dog o1, Dog o2) {
     8         if (o1.food<o2.food) return -1;
     9         else if (o1.food>o2.food) return 1;
    10         else return 0;
    11     }
    12 }
     1 public class Sorter<T> {
     2     /**
     3      * 比较方法在调用时需要传入两个参数
     4      * 第一个参数为需要参与比较的数组,数组中存放n个狗的对象
     5      * 第二个参数为狗进行比较时的具体比较策略,这个根据具体需求利用多态new出来即可
     6      */
     7     public void sort(T[] arr,Comparator<T> comparator) {
     8         for (int i=0; i<arr.length - 1; i++){
     9 
    10             int minPoint = i;
    11 
    12             for(int j=i+1; j<arr.length; j++){
    13                 minPoint = comparator.compare(arr[j], arr[minPoint] ) == -1 ? j : minPoint;
    14             }
    15             swap(arr, i, minPoint);
    16         }
    17     }
    18 
    19     void swap(T[] arr, int i , int j){
    20         T temp = arr[i];
    21         arr[i] = arr[j];
    22         arr[j] = temp;
    23     }
    24 }
     1 public class Dog {
     2 
     3     int food;
     4 
     5     public Dog(int food){
     6         this.food = food;
     7     }
     8 
     9     @Override
    10     public String toString() {
    11         return "Dog{" +
    12                 "food=" + food +
    13                 '}';
    14     }
    15 }
    1 public class Main {
    2     public static void main(String[] args) {
    3         Dog[] dogs = {new Dog(3), new Dog(5), new Dog(1)};
    4         Sorter sorter = new Sorter();
    5         sorter.sort(dogs,new DogComparator());
    6         System.out.println(Arrays.toString(dogs));
    7     }
    8 }
  • 相关阅读:
    Nginx.conf 配置文件详细说明
    CentOs中iptables配置允许mysql远程访问
    CentOS 6.4下编译安装MySQL 5.6.14
    CentOS6.4下Mysql数据库的安装与配置
    让nginx支持.htaccess文件实现伪静态的方法!
    MySQL导入.sql文件及常用命令
    PHP里10个鲜为人知但却非常有用的函数
    Nginx配置文件详细说明
    linux 开机启动nginx
    Redhat系列使用ISO或者光盘制作yum本地安装源
  • 原文地址:https://www.cnblogs.com/lyc-code/p/12390979.html
Copyright © 2011-2022 走看看