Comparator和Comparable的详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39723544/article/details/83343778

一、引言

之前在一次机试时候,考察到了Java中比较。但是答得不是很好,加之最近在学习二叉树、红黑树这些,更不离不开比较、排序,所以在这里把Java中的比较好好总结下。

二、Comparable

1. 介绍

Comparable是一个接口,是一个内比较器(至于为什么说是内比较器,在第四节就会讲到这块)。简单来说,实现了Comparable接口的类可以实现自己和自己比较了。而具体的比较规则依赖于compareTo(T o)方法,而这种比较方式则又被称为自然比较法。
Collections.sort和Arrays.sort可以直接对实现了Comparable接口的类对象进行比较排序。

2. 核心代码

public interface Comparable<T> {
	// 返回为int。分为以下三种情况:
	// 返回值等于0,则表示相等
	// 返回值大于0,则表示比较者大于被比较者
	// 返回值小于0,则表示比较者小于被比较者
	public int compareTo(T o);
}

3. 示例

public class ComparableDemo {

    public static void main(String[] args) {
        Student s1 = new Student("1110", "李四", "足球", 21);
        Student s2 = new Student("1109", "张三", "篮球", 22);
        Student s3 = new Student("1111", "王五", "排球", 23);
        Student s4 = new Student("1112", "赵六", "乒乓球", 25);
        System.out.println(s1.compareTo(s2));
        System.out.println(s1.compareTo(s3));
        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        System.out.println("--------------排序前----------");
        System.out.println(list);
        Collections.sort(list);
        System.out.println("--------------排序后----------");
        System.out.println(list);
    }

    static class Student implements Comparable<Student>{
        private String id;
        private String name;
        private String hobby;
        private Integer age;

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

        @Override
        public int compareTo(Student s) {
            // 注意:这里其实调用的是String类的compareTo的方法,因为String也实现了Comparable接口
            if (id.compareTo(s.getId()) > 0) {
                return 1;
            } else if (id.compareTo(s.getId()) == 0) {
                return 0;
            }
            return -1;
        }
	    // 省略get、set方法
    }
}

运行结果如下:
在这里插入图片描述

三、Comparator

1. 介绍

Comparator同样也是一个接口,是一个外比较器

2. 核心代码

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

	boolean equals(Object obj);
	
	// 省略其他接口中默认实现的方法
}

3. 使用场景

  1. 类虽然已实现Comparable接口,但是我对他的比较规则不满意,我想根据我自己的业务情况重新定义比较规则。这时候可以使用匿名内部的方式来达到我们的目的。
  2. 某个类我们手里只有字节码文件(拿不到源代码),不管这个类没有实现Comparable接口,我们可以通过Comparator接口达到比较的目的。

4. 示例(三种变体写法)

基础写法:

public static void main(String[] args) {
        Student s1 = new Student("1110", "李四", "足球", 29);
        Student s2 = new Student("1110", "赵六", "篮球", 22);
        Student s3 = new Student("1110", "李四", "排球", 23);
        Student s4 = new Student("1110", "赵六", "乒乓球", 25);
        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        System.out.println("--------------排序前----------");
        System.out.println(list);
        Collections.sort(list, new Comparator<Student>() {
            // 按照id,name及age比较排序。
            @Override
            public int compare(Student o1, Student o2) {
                if (o1.getName().equals(o2.getName())) {
                    if (o1.getName().equals(o2.getName())) {
                        return o1.getAge().compareTo(o2.getAge());
                    }
                    return o1.getName().compareTo(o2.getName());
                }
                return o1.getName().compareTo(o2.getName());
            }
        });
        System.out.println("--------------排序后----------");
        System.out.println(list);
    }

    static class Student implements Comparable<Student>{
        private String id;
        private String name;
        private String hobby;
        private Integer age;

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

        @Override
        public int compareTo(Student s) {
            // 注意:这里其实调用的是String类的compareTo的方法,因为String也实现了Comparable接口
            if (id.compareTo(s.getId()) > 0) {
                return 1;
            } else if (id.compareTo(s.getId()) == 0) {
                return 0;
            }
            return -1;
        }
        // 省略get、set方法
    }

结果如下:
在这里插入图片描述
变体写法1:

	// 显示创建比较器类
    static class StudentComparator implements Comparator<Student> {

        @Override
        public int compare(Student o1, Student o2) {
            if (o1.getName().equals(o2.getName())) {
                if (o1.getName().equals(o2.getName())) {
                    return o1.getAge().compareTo(o2.getAge());
                }
                return o1.getName().compareTo(o2.getName());
            }
            return o1.getName().compareTo(o2.getName());
        }
    }

	// 在main方法中这样调用
	   public static void main(String[] args) {
        Student s1 = new Student("1110", "李四", "足球", 29);
        Student s2 = new Student("1110", "赵六", "篮球", 22);
        Student s3 = new Student("1110", "李四", "排球", 23);
        Student s4 = new Student("1110", "赵六", "乒乓球", 25);
        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        System.out.println("--------------排序前----------");
        System.out.println(list);
        // 注意看这里:如果理解匿名内部类的话,这里应该很容易理解。
        StudentComparator sc = new StudentComparator();
        Collections.sort(list, sc);
        System.out.println("--------------排序后----------");
        System.out.println(list);
    }

变体写法2:
在这里插入图片描述

四、比较

1. 相同点

二者都是接口,而且都可以实现比较,进而实现排序。

2. 不同点

  • Comparable接口的耦合性较强一些,必须要在类的源代码里面进行修改。
  • 而Comparator接口则灵活性强一些,它可以在我们没有源代码的情况下,可以实现我们自定义的排序规则。

五、总结

其实具体在开发中使用哪一种接口,还是根据具体情况,选择最合适的方式进行实现。

猜你喜欢

转载自blog.csdn.net/weixin_39723544/article/details/83343778
今日推荐