欢迎光临散文网 会员登陆 & 注册

使用comparable接口对非数字类型数组排序

2022-07-01 18:00 作者:虚云幻仙  | 我要投稿

/**
* 使用comparable接口对数组排序
* 数组元素不是数字类型时 通过实现comparable接口重写规定比较方法 依据比较方法进行Arrays.sort()
*/

public class TestComparable implements Comparable{
   //实现Comparable接口
   private int id;
   private int age;
   private String name;
   //每个对象三个属性 设想通过比较age来对对象排序

   public TestComparable(){}
   public TestComparable(int id, int age, String name) {
       this.id = id;
       this.age = age;
       this.name = name;
   }

   @Override
   public int compareTo(Object o) {
       //重写实现compareTo()方法
       TestComparable t = (TestComparable)o;
       //将形参强制转型 形参o必须和接口的方法一致 形参类型改变的话不构成重写
       //重写的方法名、形参列表必须相同

       if (age<t.age){
           return -1;
       } else if (age>t.age) {
           return 1;
       }
       return 0;
   }


    @Override
    public String toString() {
       return ""+age;
       //使打印对象println(TestComparable)时默认打印对象的age属性
        //不能直接返回age 重写方法的返回值类型只能小于等于原返回值类型 int和String是        不相干的两种类型 不能更改成int
        //没法更改返回值类型就必须将age前面加""变成字符串

    }


   public static void main(String[] args) {
       TestComparable[] t = {
               new TestComparable(1,10,"Jack"),
               new TestComparable(2,12,"Jim"),
               new TestComparable(3,9,"Tom")
       };
       //太长了 换行将结构变明显
       Arrays.sort(t);
       //sort()调用compareTo()方法 根据返回值决定是否调换处于比较中的两个元素的位置 反复调整后按顺序排好元素
       System.out.println(Arrays.toString(t));
        //静态方法Arrays.toString(t)会返回String.valueOf(t[i])
        //String.valueOf(t[i]) 判断如果元素为null就返回"null" 否则返回Object.toString
        // 这里因为重写了toString 实际调用的是 t[i].toString 返回age 结果[9,10,12]

   }
}


//模拟sort()方法调用compareTo()排序的过程
interface a1{
   //定义接口a1模拟Comparable接口
   int bi(Object o);
   //接口的抽象方法 先有接口后有实现类 现阶段没有写实现类 所以形参只能写Object类或a1 因为所有类都属于Object类 这样构成了多态
   //返回值int的用法是 返回正数就认为在排序中this>o 返回负数就认为在排序中this<o 最后按照大小来排序
   //这样规定的结果是排序方法不需要自己评判两个元素哪个大哪个小 只需要调用bi()方法 bi()会返回正数或负数告诉排序方法this大还是o大
   // 排序方法看到正数就交换两个元素 看到负数就保持现状

   //排序方法只负责根据bi()返回结果对顺序进行调整 具体如何大小如何评判由实现类来规定bi()
   // 这样每个类都能有自己的评判标准 只需要按照接口和排序方法的要求格式写好bi()就能调用排序方法了
   //接口负责注释通过bi()评判大小的思路 排序方法负责根据评判结果进行排序 实现类根据自己的情况选择各自的参数(年龄、身高、体重等等)作为bi()评判的标准

}

class a2{
   public static void pai(a1[] a){
   //模拟Arrays类的sort()方法 通过调用bi()的正负值来对元素排序 思路是如果返回正数即this>o就交换两个元素 返回负数即this<o顺序正确保持现状
       //排序方法会对数组本身进行更改 所以运行完方法时实参数组已经改变了 不需要再特意返回更改的实参结果
       //用static修饰 是因为要排序的数组是本类a2以外的类的数组 不是a2[]类型 没有必要在进行排序时先new一个a2对象 再通过对象调用排序方法 这个对象的生成多此一举
       //直接指明是调用a2类的方法a2.pai()对数组进行排序 静态方法属于类
       // 静态方法内不能使用this this是用于对象名.方法(){方法体里面指代对象名的} 静态方法不属于对象没有对象所以不能用this
   //对数组进行排序的话肯定要把数组传参进方法中 因为静态方法不能通过对象名.pai()的this来指代数组 所以传参只能通过(括号内的形参) 即用形参列表表示要排序的数组
       // 具体评判大小交给bi()方法来评判 所以形参一定是实现了a1接口的实现类 形参类型写接口名构成多态 以后所有a1的实现类都能用pai()方法排序
   //排序方法中不考虑实现类怎么实现的接口 只需要认为bi()已经被按要求实现了
   //具体如何实现等到定义实现类时 按照排序方法的需求再进行设计

       //这里排序的思路是利用.bi(o)的返回值来判断大小 排序按由小到大 this比o大就返回正数 if(正数)就将this和o交换
       // 不考虑bi()方法具体怎么比较和比较了什么 只规定返回正数就是this比o大 要交换 返回负数就是this比o小不换位置


       for (int i = 0; i<a.length-1;i++){
           //排序从index=0开始
           for (int j = i+1;j<a.length;j++){
               //将index元素和后面所有元素逐一比较 返回正数即比后面的元素大就交换位置
               if (a[i].bi(a[j])>0) {
                   a1 aa = a[i];
                   a[i] = a[j];
                   a[j] = aa;
               }
           }
       }


//        //另一种方式 冒泡法 思路:从左开始依次比较相邻两个元素 左大于右即交换 比较一轮 一轮结束最右侧就是最大的 下一轮再运算出第二大的 循环直至排序完成
//        boolean ready;
//        //优化 设置一个状态值
//        for (int i =0; i<a.length; i++){
//            ready = true;
//            for (int j = 0;j<a.length-i-1;j++){
//                if (a[j].bi(a[j+1])>0){
//                    a1 aa = a[j];
//                    a[j] = a[j+1];
//                    a[j+1] =aa;
//                    ready = false;
//        //如果发生了交换 即左边比右边大 说明当前排序可能还没完全捋顺
//                }
//                if (ready)break;
       //如果在这一次for(j)循环中没有交换,即每一个左边元素都比右边元素小 比如下标0比下标1小 下标1比下标2小 那么下标0一定比下标2小
       //每一个左边都比右边小 意味着数组整体从左往右从小到大排好了 break省略剩余的循环

//            }
//        }
   }

   public static void main(String[] args) {
       a3[] x = {new a3(2),new a3(1),new a3(3)};
       //实现类a3的声明放在下面了  这里静态初始化了a3[]数组x
       pai(x);
       //对数组进行排序
       System.out.println(x[0].id);
       System.out.println(x[1].id);
       System.out.println(x[2].id);
       //结果 1 2 3
   }
}


class a3 implements a1{
   //类a3 实现 接口a1
   int id;

   public a3(int id) {
       this.id = id;
   }

   public int bi(Object a){
       //重写接口的方法 思路是通过.id的值来定大小
       //重写的方法名、形参列表要保持一致 返回值类型小于等于原类型

       a3 _a = (a3)a;
       //因为形参列表必须保持一致 所以即便知道比的对象是a3类也要用Object引用 再强转成a3类
       if (id<_a.id){
           //实现的思路是比较两个对象id的值 this.id比_a.id小的话就认为this小于_a返回负数 在pai()方法中负数就不换位置
           return -1;
       }
       return 1;
       //this大于等于_a返回正数 pai()中定义如果返回正数就将两个元素交换

       //因为pai()方法设定为if(返回正数)就交换位置 可以通过更改bi()的返回值实现排序由大到小或由小到大
       // 上面的结果是由小到大 将if(id<_a.id)改为return 1 下面改为-1就变成了由大到小
        //返回值为正数就交换 所以如果想让左边小于右边时候交换 就if(左<右)return 1 让左小于右的情况返回正数 就会实现从大到小的排序了

   }
}




使用comparable接口对非数字类型数组排序的评论 (共 条)

分享到微博请遵守国家法律