Java - Comparator

Introducing background

We know that if the data of basic data types (except boolean type) needs to be compared, comparison operators can be used directly. However, reference data types cannot be compared directly using comparison operators. So, how to solve this problem?

In Java, the sorting problem of object arrays is often involved, and then it involves the comparison problem between objects.
There are two ways to implement object sorting in Java:

  • Natural ordering: java.lang.Comparable
  • Custom sorting: java.util.Comparator

Natural ordering: java.lang.Comparable

The Comparable interface forces an overall ordering of objects of every class that implements it. This ordering is called the natural ordering of classes.

The class that implements Comparable must implement compareTo(Object obj) the method, and the two objects are compared in size through the return value of the compareTo(Object obj) method.
If the current object this is greater than the formal parameter object obj, a positive integer is returned.
If the current object this is less than the formal parameter object obj, a negative integer is returned.
If the current object this is equal to the formal parameter object obj, zero is returned.

package java.lang;

public interface Comparable{
    
    
    int compareTo(Object obj);
}

Typical implementation of Comparable: ( 默认都是从小到大排列的)

  • String: Compare according to the Unicode value of the characters in the string
  • Character: Compare according to the Unicode value of the character
  • Packaging classes corresponding to numerical types and BigInteger and BigDecimal: Compare according to their corresponding numerical sizes.
  • Boolean: The wrapper class instance corresponding to true is greater than the wrapper class instance corresponding to false
  • Date, Time, etc.: The later date and time are larger than the previous date and time

Test String

Code example:

 @Test
    public void test1(){
    
    
        //测试String已经写好的
        String [] a = new String[]{
    
    "Jack", "Tom", "Lucy"};

        //排序之前
        for (int i = 0; i < a.length; i++) {
    
    
            System.out.print(a[i]+"\t");
        }

        System.out.println();
        //使用Arrays进行排序
        Arrays.sort(a);

        //排序之后进行展示
        for (int i = 0; i < a.length; i++) {
    
    
            System.out.print(a[i]+"\t");
        }
    }

running result:

Insert image description here

Test your own implementation of the comparable interface

Product class

package cn.edu.chd.exer1;

import java.util.Objects;


public class Product implements Comparable{
    
    
    private String name;
    private double prices;

    //无参构造
    public Product() {
    
    
    }

    //全参构造
    public Product(String name, double prices) {
    
    
        this.name = name;
        this.prices = prices;
    }

    public String getName() {
    
    
        return name;
    }

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

    public double getPrices() {
    
    
        return prices;
    }

    public void setPrices(double prices) {
    
    
        this.prices = prices;
    }

    @Override
    public String toString() {
    
    
        return "Product{" +
                "name='" + name + '\'' +
                ", prices=" + prices +
                '}';
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Product product = (Product) o;
        return Double.compare(product.prices, prices) == 0 && name.equals(product.name);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(name, prices);
    }

    @Override
    public int compareTo(Object o) {
    
    
        //如果是同一个对象,return 0
        if (this == o){
    
    
            return 0;
        }

        //两个对象比较的标准是:价格从小到大,价格一样的话,按照名字从小到大
        if (o instanceof Product){
    
    
            Product p = (Product)o;
            int v = Double.compare(this.prices, p.prices);
//            return v;
            if (v != 0){
    
    
                return v;
            }
            //价格如果相同,名字按照从小到大
            return this.name.compareTo(p.name);
        }
        //手动抛异常
        throw new RuntimeException("类型不匹配");

    }
}

test

    //对不同对象的大小进行排序
    @Test
    public void test2(){
    
    

        //商品数组
        Product[] products = new Product[5];
        //全参构造器,在new对象时就对属性进行赋值
        products[0] = new Product("Huawei", 5999);
        products[1] = new Product("XiaoMi", 4999);
        products[2] = new Product("iPhone", 9999);
        products[3] = new Product("vivo", 3999);
        products[4] = new Product("Honer", 5999);


        System.out.println("排序之前");
        //排序之前的遍历
        for (int i = 0; i < products.length; i++) {
    
    
            System.out.println(products[i]);
        }

        System.out.println("----------------------------------------------");
        //使用arrays进行排序
        Arrays.sort(products);

        System.out.println("排序之后");
        //排序后的遍历
        for (int i = 0; i < products.length; i++) {
    
    
            System.out.println(products[i]);
        }
        
    }

running result

Insert image description here

Custom sorting: java.util.Comparator

think

  • When the element type does not implement the java.lang.Comparable interface and it is inconvenient to modify the code (for example: for some third-party classes, you only have the .class file and no source file)
  • If a class implements the Comparable interface, it also specifies the rules for comparing the sizes of two objects, but at this moment I don’t want to compare the sizes according to its predefined method, but I can’t modify it at will, because it will affect the use in other places. ,what to do? (For example: I want Strings to be sorted alphabetically from large to small, instead of the default from small to large)

JDK also took this situation into consideration when designing the class library, so it added a java.util.Comparator interface. Forces an overall sorted comparison of multiple objects.

  • Override the compare(Object o1, Object o2) method to compare the sizes of o1 and o2: if the method returns a positive integer, it means that o1 is greater than o2; if it returns 0, it means they are equal; if it returns a negative integer, it means that o1 is less than o2.
  • A Comparator can be passed to the sort method (such as Collections.sort or Arrays.sort), allowing precise control over the sort order.

Product class

package cn.edu.chd.exer2;

import java.util.Objects;


public class Product implements Comparable{
    
    
    private String name;
    private double prices;

    //无参构造
    public Product() {
    
    
    }

    //全参构造
    public Product(String name, double prices) {
    
    
        this.name = name;
        this.prices = prices;
    }

    public String getName() {
    
    
        return name;
    }

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

    public double getPrices() {
    
    
        return prices;
    }

    public void setPrices(double prices) {
    
    
        this.prices = prices;
    }

    @Override
    public String toString() {
    
    
        return "Product{" +
                "name='" + name + '\'' +
                ", prices=" + prices +
                '}';
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Product product = (Product) o;
        return Double.compare(product.prices, prices) == 0 && name.equals(product.name);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(name, prices);
    }

    @Override
    public int compareTo(Object o) {
    
    
        //如果是同一个对象,return 0
        if (this == o){
    
    
            return 0;
        }

        //两个对象比较的标准是:价格从小到大,价格一样的话,按照名字从小到大
        if (o instanceof Product){
    
    
            Product p = (Product)o;
            int v = Double.compare(this.prices, p.prices);
//            return v;
            if (v != 0){
    
    
                return v;
            }
            //价格如果相同,名字按照从小到大
            return this.name.compareTo(p.name);
        }
        //手动抛异常
        throw new RuntimeException("类型不匹配");

    }
}

Comparator sorted by product price from low to high

 @Test
    public void test1(){
    
    
        //new一个comparator接口的匿名实现类
        Comparator comparator = new Comparator() {
    
    
            //按照商品的价格从低到高排序
            @Override
            public int compare(Object o1, Object o2) {
    
    
                if (o1 == o2){
    
    
                    return 0;
                }
                if (o1 instanceof Product && o2 instanceof Product){
    
    
                    //强转
                    Product p1 = (Product) o1;
                    Product p2 = (Product) o2;
                    return Double.compare(p1.getPrices(), p2.getPrices());

                }
                throw new RuntimeException("类型不匹配");

            }
        };

        //商品数组
        Product[] products = new Product[5];
        //全参构造器,在new对象时就对属性进行赋值
        products[0] = new Product("Huawei", 5999);
        products[1] = new Product("XiaoMi", 4999);
        products[2] = new Product("iPhone", 9999);
        products[3] = new Product("vivo", 3999);
        products[4] = new Product("Honer", 5999);


        System.out.println("排序之前");
        //排序之前的遍历
        for (int i = 0; i < products.length; i++) {
    
    
            System.out.println(products[i]);
        }

        System.out.println("----------------------------------------------");
        //将comparator对象作为参数进行传入,排序
        Arrays.sort(products, comparator);

        System.out.println("排序之后");
        //排序后的遍历
        for (int i = 0; i < products.length; i++) {
    
    
            System.out.println(products[i]);
        }



        
    }

running result:

Insert image description here

comparator sorted by name

   //按照名称进行排序
    @Test
    public void test2(){
    
    
        //new一个comparator接口的匿名实现类
        Comparator comparator = new Comparator() {
    
    
            //按照商品的名称进行排序
            @Override
            public int compare(Object o1, Object o2) {
    
    
                if (o1 == o2){
    
    
                    return 0;
                }
                if (o1 instanceof Product && o2 instanceof Product){
    
    
                    //强转
                    Product p1 = (Product) o1;
                    Product p2 = (Product) o2;
                    return p1.getName().compareTo(p2.getName());

                }
                throw new RuntimeException("类型不匹配");

            }
        };

        //商品数组
        Product[] products = new Product[5];
        //全参构造器,在new对象时就对属性进行赋值
        products[0] = new Product("Huawei", 5999);
        products[1] = new Product("XiaoMi", 4999);
        products[2] = new Product("iPhone", 9999);
        products[3] = new Product("vivo", 3999);
        products[4] = new Product("Honer", 5999);


        System.out.println("排序之前");
        //排序之前的遍历
        for (int i = 0; i < products.length; i++) {
    
    
            System.out.println(products[i]);
        }

        System.out.println("----------------------------------------------");
        //将comparator对象作为参数进行传入,排序
        Arrays.sort(products, comparator);

        System.out.println("排序之后");
        //排序后的遍历
        for (int i = 0; i < products.length; i++) {
    
    
            System.out.println(products[i]);
        }


    }

running result:

Insert image description here

Guess you like

Origin blog.csdn.net/Elon15/article/details/132831926