javaSE基础-比较器

Java比较器

1、java对象正常情况下只能进行 == 或 !=,不能进行比较大小。
若需要比较对象的大小,需要实现两个接口中的任何一个:Comparable 或 Comparator

2、Comparable接口与Comparator接口的使用比较
Comparable接口的方式一旦指定,该接口的实现类的对象可以在任何位置都可以比较大小
Comparator接口属于临时性的比较

Comparable接口

1、String、包装类等实现了Comparable接口,重写CompareTo(obj)或compare方法,给出了比较两个对象的方式

2、重写了CompareTo(obj)的方法以后,默认进行从小到大的排序

3、重写compareTo(obj)的规则:

  • 如果当前对象的this大于形参对象obj,则返回正整数

  • 如果当前对象的this小于形参对象obj,则返回负整数

  • 如果当前对象的this等于形参对象obj,则返回零

4、(自然排序)对于自定义类,如需要排序,可以让自定义类实现Comparable接口,重写compareTo(obj)的方法,在compareTo(obj)的方法中指明如何排序

示例

@Test
public void test1(){
    String[] arr = new String[]{"aa","bb","dd","cc","zz","mm"};
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));//[aa, bb, cc, dd, mm, zz]
}

商品类Goods,声明name和price属性

//实现Comparable接口
public class Goods implements Comparable{
    private String name;
    private Integer price;

    public Goods(String name, Integer price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
	
    //重写comparaTo方法:具体的比较方式声明在此方法体中
    @Override
    public int compareTo(Object o) {
        //方式一:
        if(o instanceof Goods){
            Goods obj = (Goods)o;
            if(obj.price < this.price){
                return 1;
            }else if(obj.price > this.price){
                return -1;
            }else {
                //return 0;
                return -this.name.compareTo(obj.name);
            }
            //方式二:
            //return Double.compare(obj.price, this.price);
        }
        throw new RuntimeException("输入的数据不一致!");

    }
}

测试

@Test
public void test2(){
    Goods[] arr = new Goods[5];
    arr[0] = new Goods("xiaomi phone", 3999);
    arr[1] = new Goods("huawei phone", 8899);
    arr[2] = new Goods("apple phone", 8999);
    arr[3] = new Goods("vivo phone", 4999);
    arr[4] = new Goods("opple phone", 8899);

    Arrays.sort(arr);

    System.out.println(Arrays.toString(arr));
}

Comparator接口

Comparator接口的使用:定制排序,解决没有实现java.lang.comparable接口或者不便修改原代码,或者原来的接口排序不满足要求,就可以实现定制Comparator接口。

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:

  • o1大于o2,则返回正整数
  • o1等于o2,则返回0
  • o1小于o2,则返回负整数

示例

@Test
public void test3(){
    String[] arr = new String[]{"aa","bb","dd","cc","zz","mm"};

    //字符串从大到小排序
    Arrays.sort(arr, new Comparator() {//匿名实现类匿名对象
        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof String && o2 instanceof String){
                String obj1 = (String) o1;
                String obj2 = (String) o2;
                return -obj1.compareTo(obj2);
            }
            throw new RuntimeException("数据类型不一致");
        }
    });

    System.out.println(Arrays.toString(arr));
}

@Test
public void test4(){
    Goods[] arr = new Goods[6];
    arr[0] = new Goods("xiaomi phone", 3999);
    arr[1] = new Goods("huawei phone", 8899);
    arr[2] = new Goods("apple phone", 8999);
    arr[3] = new Goods("apple phone", 10999);
    arr[4] = new Goods("vivo phone", 4999);
    arr[5] = new Goods("opple phone", 8899);

    //指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序
    Arrays.sort(arr, new Comparator<Goods>() {
        @Override
        public int compare(Goods o1, Goods o2) {
            if(o1.getName().equals(o2.getName())){
                //xxx.compare()默认从小到大
                return -Double.compare(o1.getPrice(),o2.getPrice());
            }else {
                return o1.getName().compareTo(o2.getName());
            }
        }
    });

    System.out.println(Arrays.toString(arr));
}

使用比较器的场景:

Arrays.sort(goods, com);

Collections.sort(coll, com);

new TreeSet(com);

new TreeMap(com);

两种排序方式的比较

Comparable接口的方式一旦确定,保证Comparable接口实现类的对象在任何位置都可以比较

Comparator接口属于临时性比较

案例一: TreeSet的使用

实体类 - MyDate.java

/**
 * MyDate类成员变量:
 * year,month,day
 */
public class MyDate {
    private int year;
    private int month;
    private int day;

    public MyDate() {
    }

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
	...
}

Employee.java

/**
 * Employee类成员变量:
 * name,age,birthday(为MyDate类的对象)
 */
public class Employee implements Comparable{
    private String name;
    private Integer age;
    private MyDate birthday;

    public Employee() {
    }

    public Employee(String name, Integer age, MyDate birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

	...

    @Override
    public int compareTo(Object o) {
        if(o instanceof Employee){
            Employee e = (Employee)o;
            return this.getName().compareTo(e.getName());
        }
        throw new RuntimeException("输入的数据类型不匹配");
    }
}

测试一

//使用:自然排序
@Test
public void test1(){
    TreeSet set = new TreeSet();

    Employee e1 = new Employee("liudehua", 51, new MyDate(1973, 4, 9));
    Employee e2 = new Employee("zhangxueyou", 52, new MyDate(1953, 4, 9));
    Employee e3 = new Employee("guofucheng", 63, new MyDate(1942, 8, 11));
    Employee e4 = new Employee("liming", 42, new MyDate(1983, 8, 29));
    Employee e5 = new Employee("liangzhaowei", 66, new MyDate(1936, 6,19));

    set.add(e1);
    set.add(e2);
    set.add(e3);
    set.add(e4);
    set.add(e5);

    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

//结果
Employee{name='guofucheng', age=63, birthday=MyDate{year=1942, month=8, day=11}}
Employee{name='liangzhaowei', age=66, birthday=MyDate{year=1936, month=6, day=19}}
Employee{name='liming', age=42, birthday=MyDate{year=1983, month=8, day=29}}
Employee{name='liudehua', age=51, birthday=MyDate{year=1973, month=4, day=9}}
Employee{name='zhangxueyou', age=52, birthday=MyDate{year=1953, month=4, day=9}

测试二

//按照:生日排序,定制排序
@Test
public void test2(){

    TreeSet set = new TreeSet(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof Employee && o2 instanceof Employee){
                Employee b1 = (Employee) o1;
                Employee b2 = (Employee) o2;
                MyDate d1 = b1.getBirthday();
                MyDate d2 = b2.getBirthday();
                //比较年
                int subYear = d1.getYear() - d2.getYear();
                if(subYear != 0){
                    return subYear;
                }
                //比较月
                int subMonth = d1.getMonth() - d2.getMonth();
                if(subMonth != 0){
                    return subMonth;
                }
                //比较日
                int subDay = d1.getDay() - d2.getDay();
                if(subDay != 0){
                    return subDay;
                }
                //在birthday相同的情况下比较name
                return b1.getName().compareTo(b2.getName());
            }
            throw new RuntimeException("输入的数据不匹配!");
        }
    });

    Employee e1 = new Employee("zhangxueyou", 51, new MyDate(1973, 4, 9));
    Employee e2 = new Employee("liudehua", 52, new MyDate(1973, 4, 9));
    Employee e3 = new Employee("guofucheng", 63, new MyDate(1942, 8, 11));
    Employee e4 = new Employee("liming", 42, new MyDate(1942, 8, 9));
    Employee e5 = new Employee("liangzhaowei", 66, new MyDate(1936, 6,19));

    set.add(e1);
    set.add(e2);
    set.add(e3);
    set.add(e4);
    set.add(e5);

    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}
//结果
Employee{name='liangzhaowei', age=66, birthday=MyDate{year=1936, month=6, day=19}}
Employee{name='liming', age=42, birthday=MyDate{year=1942, month=8, day=9}}
Employee{name='guofucheng', age=63, birthday=MyDate{year=1942, month=8, day=11}}
Employee{name='liudehua', age=52, birthday=MyDate{year=1973, month=4, day=9}}
Employee{name='zhangxueyou', age=51, birthday=MyDate{year=1973, month=4, day=9}}

案例二: TreeMap的使用

//User.java
class User implements Comparable {
    private String name;
    private Integer age;

    public User() {
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    
    ...
        
    @Override
    public int compareTo(Object o) {
        if(o instanceof User){
            User user = (User)o;
            //按照姓名的字母从大到小排序
            //return -user.name.compareTo(this.name);

            int compara = user.name.compareTo(this.name);
            if(compara != 0){
                return compara;
            }else {
                //在姓名相同的情况下:比较年龄的,从小到大
                return -Integer.compare(user.getAge(), this.getAge());
            }

        }else {
            throw new RuntimeException("输入数据类型不一致");
        }
    }
}

示例:按照key自然排序

@Test
public void test5(){
    TreeMap treeMap = new TreeMap();
    User u1 = new User("Jack", 34);
    User u2 = new User("Mary", 54);
    User u3 = new User("Jam", 24);
    User u4 = new User("Tom", 19);

    treeMap.put(u1, 99);
    treeMap.put(u2, 45);
    treeMap.put(u3, 18);
    treeMap.put(u4, 19);

    Set set = treeMap.keySet();
    Iterator iter = set.iterator();
    while (iter.hasNext()){
        Object key = iter.next();
        Object value = treeMap.get(key);
        System.out.println(key + "===" + value);
    }
}
//结果
Person{name='Tom', age=19}===19
Person{name='Mary', age=54}===45
Person{name='Jam', age=24}===18
Person{name='Jack', age=34}===99

示例:按照key定制排序

@Test
public void test6(){
    TreeMap treeMap = new TreeMap(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof User && o2 instanceof  User){
                User u1 = (User) o1;
                User u2 = (User) o2;
                //按照年龄 从小到大
                return Integer.compare(u1.getAge(), u2.getAge());
            }
            throw new RuntimeException("输入数据不匹配");
        }
    });
    User u1 = new User("Jack", 34);
    User u2 = new User("Mary", 54);
    User u3 = new User("Jam", 24);
    User u4 = new User("Tom", 19);

    treeMap.put(u1, 99);
    treeMap.put(u2, 45);
    treeMap.put(u3, 18);
    treeMap.put(u4, 19);

    Set set = treeMap.keySet();
    Iterator iter = set.iterator();
    while (iter.hasNext()){
        Object key = iter.next();
        Object value = treeMap.get(key);
        System.out.println(key + "===" + value);
    }
}
//结果
Person{name='Tom', age=19}===19
Person{name='Jam', age=24}===18
Person{name='Jack', age=34}===99
Person{name='Mary', age=54}===45
posted @ 2022-10-27 21:12  Bingeone  阅读(45)  评论(0编辑  收藏  举报