CompareTo 和caompare的初步理解,以及一些错误案例的展示

继承Comparable的实体类

package com.hantao.sortTest;

public class User implements Comparable<Object>{
    int id;
    String name;
    int  mainId;

    public int getMainId() {
        return mainId;
    }

    public void setMainId(int mainId) {
        this.mainId = mainId;
    }

    public User(int id, String name, int mainId) {
        this.id = id;
        this.name = name;
        this.mainId = mainId;
    }

    /*
     * Getters and Setters
     */
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", mainId=" + mainId +
                '}';
    }

    /**
     *负数代表左值小于右值,排在上面
     *正数代表左值大于右值,排在下面
     *0代表左值等于右值,排在上面
     * @param o
     * @return
     */
    @Override
    public int compareTo(Object o) {
        //可以这样理解:排序就是比较谁大谁小,将小的放在前面,大的放在后面。
        // 例如当返回负数的时候,表明第一个数应该排在第二个数的上面。

        //可以按照你想要的规则进行排序,不论是按照集合中的正序(返回值1),
        // 还是集合中的倒序(返回值-1)还是按照字典排序(如上)都是可以的。


        //1、如果字符串相等返回值0
        //2、如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值代表:前字符串的值小于后字符串,正值代表:前字符串大于后字符串)
        //3、如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符的长度. 
        //负值代表:前字符串的值小于后字符串,正值代表:前字符串大于后字符串
        //字符串越小的放在越前面。

        //同一个对象
        System.out.println("左侧为"+this.toString()+":右侧为"+o.toString());
        if(this ==o){
            User u = (User) o;
            System.out.println("左边==右侧,将"+mainId+"放在"+u.mainId+"前面");
            //负数代表左值小于右值,排在上面
            //正数代表左值大于右值,排在下面
            //0代表左值等于右值,排在上面
            return 0;
        }
        else if (o instanceof User) {
            User u = (User) o;
            if(id<=u.id){
                //(this.id-u.id)为负数    从小到大排序
                //想要从小到大排序,修改为(u.id-this.id)为负数
                System.out.println( "左边<右侧,将"+mainId+"放在"+u.mainId+"前面");
                return -1;
            }else{
                System.out.println("左边>右侧,将"+u.mainId+"放在"+mainId+"前面");
                return 1;
            }
        }else{
            System.out.println("报错");
            return -1;
        }
    }
}

test类

然后写一个Test类进行运行

package com.hantao.sortTest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class UserTest2 {
  //编写Comparator,根据User的id对User进行排序
        private static final Comparator<User> COMPARATOR = new Comparator<User>() {
        public int compare(User o1, User o2) {
            return o1.compareTo(o2);//运用User类的compareTo方法比较两个对象
        }
    };
        public static void main(String[] args) {
            ArrayList<User> student = new ArrayList<User>();
            User user1 = new User(1,"zhongjingzou",1);
            User user5 = new User(2,"zhongjingzou4",4);
            User user4 = new User(2,"zhongjingzou3",3);
            User user2 = new User(2,"zhongjingzou2",2);
            User user6 =user5;
            User user7 =user5;

            student.add(user1);
            student.add(user5);
            student.add(user2);
            student.add(user4);
            student.add(user7);
            student.add(user6);




            Collections.sort(student, COMPARATOR);
            for(int i=0;i<student.size();i++){
                System.out.println(student.get(i).toString());
            }

            Collections.sort(student,new Comparator<User>() {
                @Override
                public int compare(User u1, User u2) {
                    //先倒序排序(从大到小)左边的参数和右边的参数相对传入的顺序倒置
                    int fileType = u2.getId() - u1.getId();
                    //想要正序排列(从小到大) 左边的参数和右边的参数按照传入的顺序
                    //int fileType = u1.getId() - u2.getId();
                    if (fileType == 0) {
                        //1、如果字符串相等返回值0
                        //2、如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值代表:前字符串的值小于后字符串,正值代表:前字符串大于后字符串)
                        //3、如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符的长度. 
                        //负值代表:前字符串的值小于后字符串,正值代表:前字符串大于后字符串
                        //字符串越小的放在越前面。
                        return u1.getName().compareToIgnoreCase(u2.getName());
                    }
                    return fileType;
                }
            });
            for(int i=0;i<student.size();i++){
                System.err.println(student.get(i).toString());
            }
        }
}

个人理解:

返回值的正,负,0

*负数代表左值小于右值,左值插入到当前右值的上面(前面)
*正数代表左值大于右值,右值插入到当前左值的上面(前面)
*0代表左值等于右值,左值插入到当前右值的上面(前面)

测试1:

首先我们来查看一下 

//编写Comparator,根据User的id对User进行排序
        private static final Comparator<User> COMPARATOR = new Comparator<User>() {
        public int compare(User o1, User o2) {
            return o1.compareTo(o2);//运用User类的compareTo方法比较两个对象
        }
    };

的效果。

左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在4前面
Disconnected from the target VM, address: '127.0.0.1:56748', transport: 'socket'
左侧为User{id=2, name='zhongjingzou2', mainId=2}:右侧为User{id=2, name='zhongjingzou4', mainId=4}
左边<右侧,将2放在4前面
左侧为User{id=2, name='zhongjingzou2', mainId=2}:右侧为User{id=2, name='zhongjingzou4', mainId=4}
左边<右侧,将2放在4前面
左侧为User{id=2, name='zhongjingzou2', mainId=2}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在2前面
左侧为User{id=2, name='zhongjingzou3', mainId=3}:右侧为User{id=2, name='zhongjingzou2', mainId=2}
左边<右侧,将3放在2前面
左侧为User{id=2, name='zhongjingzou3', mainId=3}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在3前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou2', mainId=2}
左边<右侧,将4放在2前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou3', mainId=3}
左边<右侧,将4放在3前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在4前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou3', mainId=3}
左边<右侧,将4放在3前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou4', mainId=4}
左边==右侧,将4放在4前面
User{id=1, name='zhongjingzou', mainId=1}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou3', mainId=3}
User{id=2, name='zhongjingzou2', mainId=2}
User{id=2, name='zhongjingzou4', mainId=4} 

可以根据描述的语句自己动手一下,看一下写的顺序是否一致。

然后修改一下list中add的顺序,可以发现相等的

  student.add(user1);
            student.add(user2);
            student.add(user4);
            student.add(user5);
            student.add(user6);
            student.add(user7);

左侧为User{id=2, name='zhongjingzou2', mainId=2}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在2前面
左侧为User{id=2, name='zhongjingzou3', mainId=3}:右侧为User{id=2, name='zhongjingzou2', mainId=2}
左边<右侧,将3放在2前面
左侧为User{id=2, name='zhongjingzou3', mainId=3}:右侧为User{id=2, name='zhongjingzou2', mainId=2}
左边<右侧,将3放在2前面
左侧为User{id=2, name='zhongjingzou3', mainId=3}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在3前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou3', mainId=3}
左边<右侧,将4放在3前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=1, name='zhongjingzou', mainId=1}
左边>右侧,将1放在4前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou3', mainId=3}
左边<右侧,将4放在3前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou4', mainId=4}
左边==右侧,将4放在4前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou4', mainId=4}
左边==右侧,将4放在4前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou2', mainId=2}
左边<右侧,将4放在2前面
左侧为User{id=2, name='zhongjingzou4', mainId=4}:右侧为User{id=2, name='zhongjingzou3', mainId=3}
左边<右侧,将4放在3前面
User{id=1, name='zhongjingzou', mainId=1}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou3', mainId=3}
User{id=2, name='zhongjingzou2', mainId=2}

修改add的顺序可以发现输出的结构有差异。

相同的对象(地址值一样)在list中的位置不一致也将导致排序的问题出现。

测试2:

然后来看一下

 Collections.sort(student,new Comparator<User>() {
                @Override
                public int compare(User u1, User u2) {
                    //先倒序排序(从大到小)左边的参数和右边的参数相对传入的顺序倒置
                    int fileType = u2.getId() - u1.getId();
                    //想要正序排列(从小到大) 左边的参数和右边的参数按照传入的顺序
                    //int fileType = u1.getId() - u2.getId();
                    if (fileType == 0) {
                        //1、如果字符串相等返回值0
                        //2、如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值代表:前字符串的值小于后字符串,正值代表:前字符串大于后字符串)
                        //3、如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符的长度. 
                        //负值代表:前字符串的值小于后字符串,正值代表:前字符串大于后字符串
                        //字符串越小的放在越前面。
                        return u1.getName().compareToIgnoreCase(u2.getName());
                    }
                    return fileType;
                }
            });

对应的结果

 

student.add(user1);
student.add(user2);
student.add(user4);
student.add(user5);
student.add(user6);
student.add(user7);

结果如下:

User{id=2, name='zhongjingzou2', mainId=2}
User{id=2, name='zhongjingzou3', mainId=3}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=1, name='zhongjingzou', mainId=1}

student.add(user1);
student.add(user5);
student.add(user2);
student.add(user4);
student.add(user7);
student.add(user6);

结果如下:

User{id=2, name='zhongjingzou2', mainId=2}
User{id=2, name='zhongjingzou3', mainId=3}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=2, name='zhongjingzou4', mainId=4}
User{id=1, name='zhongjingzou', mainId=1}

两次结果一致,可以思考一下为何这次add的顺序并没有导致之前相同地址值的排序sort出异常的情况。

 

附上相关int类型测试sort方法的测试Demo

import java.util.*;


public class SortTest {
    public void arraySort(){
        int[] arr = {1,4,6,333,8,2};
        Arrays.sort(arr);//使用java.util.Arrays对象的sort方法
        for(int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }
    }
    public void listSort1(){
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(55);
        list.add(9);
        list.add(0);
        list.add(2);
        Collections.sort(list);//使用Collections的sort方法
        for(int a :list){
            System.out.println(a);
        }
    }
    //对list降序排序
    public void listSort2(){
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(55);
        list.add(9);
        list.add(0);
        list.add(2);
        //升序排列
        Collections.sort(list, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });//使用Collections的sort方法,并且重写compare方法
        for(int a :list){
            System.out.println(a);
        }
        //降序排列
        System.out.println("从大到小");
        Collections.sort(list, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });//使用Collections的sort方法,并且重写compare方法
        for(int a :list){
            System.out.println(a);
        }
    }

}

错误示例: 永远无法返回正值,永远只返回负值,无法正常排序。

照这么比,o1永远比o2要小那当然不能排序。

package com.lin;
 
import java.util.Comparator;
 
public class ComparatorTest implements Comparator<Student> {
 
    @Override
    public int compare(Student o1, Student o2) {
        if(o1.getAge() < o2.getAge()){
            int num = o1.getAge() - o2.getAge();
//            System.out.println(num);
            return num;
        }else{
            int num = o2.getAge() - o1.getAge();
//            System.out.println(num);
            return num;
        }
    }
}

 

相关:

【转】Java中Collections.sort()和Arrays.sort()所采用的排序算法

https://www.cnblogs.com/merru/articles/4666493.html

 

 

 

 

  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值