栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java比较器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java比较器

1. 简介

在Java中对于基本数据类型,诸如Integer、double等,java可以对它们进行比较,我们开发人员不需要做任何其他的工作,但对于复杂数据类型,比如类的比较,需要开发人员定义比较的逻辑,这种比较逻辑,Java中提供了两种实现,一种是内部比较器Comparable,另一种是外部比较器Comparator,这两个比较器都是Java接口。

2. 源码介绍(Java8)

内部比较器Comparable源代码在java.lang下,里面只有一个方法public int compareTo(T o);支持泛型,具体源码如下:


package java.lang;
import java.util.*;


public interface Comparable {
    
    public int compareTo(T o);
}

外部比较器Comparator也是一个支持泛型的接口,在java.util包下,里面有如下的成员,比较器逻辑,在它的int compare(T o1, T o2);方法中实现。

源代码如下:


package java.util;

import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;


@FunctionalInterface
public interface Comparator {
    
    int compare(T o1, T o2);

    
    boolean equals(Object obj);

    
    default Comparator reversed() {
        return Collections.reverseOrder(this);
    }

    
    default Comparator thenComparing(Comparator other) {
        Objects.requireNonNull(other);
        return (Comparator & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }

    
    default  Comparator thenComparing(
            Function keyExtractor,
            Comparator keyComparator)
    {
        return thenComparing(comparing(keyExtractor, keyComparator));
    }

    
    default > Comparator thenComparing(
            Function keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }

    
    default Comparator thenComparingInt(ToIntFunction keyExtractor) {
        return thenComparing(comparingInt(keyExtractor));
    }

    
    default Comparator thenComparingLong(ToLongFunction keyExtractor) {
        return thenComparing(comparingLong(keyExtractor));
    }

    
    default Comparator thenComparingDouble(ToDoubleFunction keyExtractor) {
        return thenComparing(comparingDouble(keyExtractor));
    }

    
    public static > Comparator reverseOrder() {
        return Collections.reverseOrder();
    }

    
    @SuppressWarnings("unchecked")
    public static > Comparator naturalOrder() {
        return (Comparator) Comparators.NaturalOrderComparator.INSTANCE;
    }

    
    public static  Comparator nullsFirst(Comparator comparator) {
        return new Comparators.NullComparator<>(true, comparator);
    }

    
    public static  Comparator nullsLast(Comparator comparator) {
        return new Comparators.NullComparator<>(false, comparator);
    }

    
    public static  Comparator comparing(
            Function keyExtractor,
            Comparator keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

    
    public static > Comparator comparing(
            Function keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

    
    public static  Comparator comparingInt(ToIntFunction keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator & Serializable)
            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }

    
    public static  Comparator comparingLong(ToLongFunction keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator & Serializable)
            (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
    }

    
    public static Comparator comparingDouble(ToDoubleFunction keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator & Serializable)
            (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
    }
}
3. 使用

内部比较器使用:实现了Comparable接口的类需要实现compareTo()方法,传入一个外部参数进行比对。

class Apple implements Comparable{
    int id;
    double price;
 
    public Apple(int id, double price) {
        this.id = id;
        this.price = price;
    }
    public int compareTo(Apple o) {
        //return Double.compare(this.getPrice(),o.getPrice());
        if (Math.abs(this.price-o.price)<0.001)
            return 0;
        else
            return (o.price-this.price)>0?1:-1;
    }
    @Override
    public String toString() {
        return "Apple{" +
                "id=" + id +
                ", price=" + price +
                '}';
    }
}

外部比较器使用:实现了Comparator接口的方法需要实现compare()方法,对外部传入的两个类进行比较,从而让外部方法在比较时调用。

class AESComparator implements Comparator{
 
    public int compare(Apple o1, Apple o2) {
        if (Math.abs(o1.price-o2.price)<0.001)
            return 0;
        else{
            return (o1.price-o2.price)>0?1:-1;
        }
    }
}

内部比较器与外部比较器对比:

  • 所在Java源码中位置不同,上面有提到
  • 实现比较逻辑的方法不同
  • Comparator接口代码更加灵活,与类的定义解耦,可以定义某个类的多个比较器,从而在排序时根据实际场景自由调用,Comparable接口实现后便不能改动,需要将比较的逻辑嵌入到类定义的内部,耦合度较高,
4.关于比较器的一点说明
    public static class IdShengAgeJiangOrder implements Comparator {

        // 根据id从小到大,但是如果id一样,按照年龄从大到小
        @Override
        public int compare(Student o1, Student o2) {
            return o1.id != o2.id ? (o1.id - o2.id) : (o2.age - o1.age);
        }

    }
	
	public static void main(String[] args) {
		Arrays.sort(students, new IdShengAgeJiangOrder());
	}

任何比较器:
compare方法里,遵循一个统一的规范:
返回负数的时候,认为第一个参数应该排在前面
返回正数的时候,认为第二个参数应该排在前面
返回0的时候,认为无所谓谁放前面

补充:Collections类是一个包装类,它包含有各种有关集合操作的静态方法。就像一个工具类。
public static void sort(List list,Comparator<>),根据指定比较器产生的顺序对指定列表进行排序,此列表内的所有元素都必须可使用指定的比较器相互比较

5. 练习
package Sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.TreeMap;


public class Code01_Comparator {

    public static class Student {
        public String name;
        public int id;
        public int age;

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

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + ''' +
                    ", id=" + id +
                    ", age=" + age +
                    '}';
        }
    }

    // 任何比较器:
    // compare方法里,遵循一个统一的规范:
    // 返回负数的时候,认为第一个参数应该排在前面
    // 返回正数的时候,认为第二个参数应该排在前面
    // 返回0的时候,认为无所谓谁放前面
    public static class IdShengAgeJiangOrder implements Comparator {

        // 根据id从小到大,但是如果id一样,按照年龄从大到小
        @Override
        public int compare(Student o1, Student o2) {
            return o1.id != o2.id ? (o1.id - o2.id) : (o2.age - o1.age);
        }

    }

    public static class IdAscendingComparator implements Comparator {

        // 返回负数的时候,第一个参数排在前面
        // 返回正数的时候,第二个参数排在前面
        // 返回0的时候,谁在前面无所谓
        @Override
        public int compare(Student o1, Student o2) {
            return o1.id - o2.id;
        }

    }

    public static class IdDescendingComparator implements Comparator {

        @Override
        public int compare(Student o1, Student o2) {
            return o2.id - o1.id;
        }

    }

    // 先按照id排序,id小的,放前面;
    // id一样,age大的,前面;
    public static class IdInAgeDe implements Comparator {

        @Override
        public int compare(Student o1, Student o2) {
            return o1.id != o2.id ? o1.id - o2.id : (o2.age - o1.age);
        }

    }

    public static void printStudents(Student[] students) {
        for (Student student : students) {
            System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age);
        }
    }

    public static void printArray(Integer[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static class MyComp implements Comparator {

        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }

    }

    public static class AComp implements Comparator {

        // 如果返回负数,认为第一个参数应该拍在前面
        // 如果返回正数,认为第二个参数应该拍在前面
        // 如果返回0,认为谁放前面都行
        @Override
        public int compare(Integer arg0, Integer arg1) {

            return arg1 - arg0;

//			return 0;
        }

    }

    public static void main(String[] args) {

        Integer[] arr = { 5, 4, 3, 2, 7, 9, 1, 0 };

        Arrays.sort(arr, new AComp());

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        System.out.println("===========================");

        Student student1 = new Student("A", 4, 40);
        Student student2 = new Student("B", 4, 21);
        Student student3 = new Student("C", 3, 12);
        Student student4 = new Student("D", 3, 62);
        Student student5 = new Student("E", 3, 42);
        // D E C A B

        Student[] students = new Student[] { student1, student2, student3, student4, student5 };
        System.out.println("第一条打印");

        Arrays.sort(students, new IdShengAgeJiangOrder());
//        for (int i = 0; i < students.length; i++) {
//            Student s = students[i];
//            System.out.println(s.name + "," + s.id + "," + s.age);
//        }
        System.out.println(Arrays.toString(students));

        System.out.println("第二条打印");
        ArrayList studentList = new ArrayList<>();
        studentList.add(student1);
        studentList.add(student2);
        studentList.add(student3);
        studentList.add(student4);
        studentList.add(student5);
        studentList.sort(new IdShengAgeJiangOrder());
        for (int i = 0; i < studentList.size(); i++) {
            Student s = studentList.get(i);
            System.out.println(s.name + "," + s.id + "," + s.age);
        }
        // N * logN
        System.out.println("第三条打印");
        student1 = new Student("A", 4, 40);
        student2 = new Student("B", 4, 21);
        student3 = new Student("C", 4, 12);
        student4 = new Student("D", 4, 62);
        student5 = new Student("E", 4, 42);
        TreeMap treeMap = new TreeMap<>((a, b) -> (a.id - b.id));
        treeMap.put(student1, "我是学生1,我的名字叫A");
        treeMap.put(student2, "我是学生2,我的名字叫B");
        treeMap.put(student3, "我是学生3,我的名字叫C");
        treeMap.put(student4, "我是学生4,我的名字叫D");
        treeMap.put(student5, "我是学生5,我的名字叫E");
        for (Student s : treeMap.keySet()) {
            System.out.println(s.name + "," + s.id + "," + s.age);
        }

    }

}

6.完结撒花
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号