Java 之 Comparable vs Comparator

简介: Comparable和Compator都是用于给集合排序的接口,但是他们之间的区别是什么呢。Comparable: 这个接口只有一个方法compareTo。

Comparable和Compator都是用于给集合排序的接口,但是他们之间的区别是什么呢。

  • Comparable: 这个接口只有一个方法compareTo。比如我们想通过年龄给用户排序,那么我们的用户要实现Comparable接口的方法,假如一旦要通过用户的评分进行排序,我们就必须要修改compareTo方法。
// o 是要比较的对象
// 返回负数,小于要比较的对象
// 返回 0 ,等于要比较的对象
// 返回正数,大于要比较的对象
public interface Comparable<T> {
    public int compareTo(T o);
}    
  • Comparator: 这个接口有两个方法,equals和compare. 要进行比较的类不一定非要实现Comparator接口,由第三方的类实现这个接口来进行排序。 这样的话,排序的种类就可以有很多种,并且像对用户进行排序,我们可以通过年龄,姓名,评分等进行排序也不用修改用户类。我们要做的应该就是写 AgeComparator,NameComparator,RankComparator.
public interface Comparator<T> {
// 返回负数,第一个小于第二个的对象,o1 < o2
// 返回 0 ,对象相等  o1 = o2
// 返回正数,第一个大于第二个对象 o1 > o2
    int compare(T o1, T o2);

  
    // 判断Compator之间是不是相同的
    boolean equals(Object obj);
}

案例

通过Comaparable排序
  1. 如果是通过评分(rank)进行排序,User类写法如下
public class User implements Comparable<User>{
    private Integer id;
    private Integer rank;
    private Integer age;
    private String name;

    //getter and setter
    
    public User(Integer rank, Integer age, String name) {
        this.rank = rank;
        this.age = age;
        this.name = name;
    }
    
    // 通过rank进行排序
    @Override
    public int compareTo(User o) {
        return this.getRank() - o.getRank();
    }
    
     @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", rank=" + rank +
                ", age=" + age +
                '}';
    }
}

  1. 如果想要通过年龄进行排序,那么就要修改User对象。
public class User implements Comparable<User>{
    private Integer id;
    private Integer rank;
    private Integer age;
    private String name;

    //getter and setter
    
    public User(Integer rank, Integer age, String name) {
        this.rank = rank;
        this.age = age;
        this.name = name;
    }
    
    // 通过rank进行排序
    @Override
    public int compareTo(User o) {
        return this.getAge() - o.getAge();
    }
    
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", rank=" + rank +
                ", age=" + age +
                '}';
    }
}
  1. 写测试类。
public class App {
    public static void main(String[] args) {
        List<User> list = new ArrayList<User>();
        list.add(new User("aihe",100,23));
        list.add(new User("weidong",80,25));
        list.add(new User("zhangbo",85,28));
        list.add(new User("leizhen",90,29));
        Collections.sort(list);
        System.out.println(list);
    }
}
通过Comparator进行排序
  1. 如果是通过Rank进行排序,创建RankComparator类。
public class RankComparator implements Comparator<User> {
    // 通过rank进行排序
    public int compare(User o1, User o2) {
        return o1.getRank() - o2.getRank();
    }
}
  1. 如果是通过年龄进行排序,创建AgeComparator类。
public class AgeComparator implements Comparator<User> {
    // 通过age进行排序
    public int compare(User o1, User o2) {
        return o1.getAge() - o2.getAge();
    }
}
  1. 测试类。
public class App {
    public static void main(String[] args) {
        List<User> list = new ArrayList<User>();
        list.add(new User("aihe",100,23));
        list.add(new User("weidong",80,25));
        list.add(new User("zhangbo",85,28));
        list.add(new User("leizhen",90,29));
        Collections.sort(list,new RankComparator());
        //Collections.sort(list,new AgeComparator());
        System.out.println(list);
    }
}

小结

如果我们的排序方式一般不会变化,我们知道要排序什么字段,在创建对象的时候可以直接实现Comparable接口。

如果我们还不清楚要比较什么字段,那么可以等到后续确定的时候实现Comparator接口,Comparator接口是从外部进行排序,不会对对象产生影响。

参考

相关文章
|
4月前
|
存储 缓存 安全
HashMap VS TreeMap:谁才是Java Map界的王者?
HashMap VS TreeMap:谁才是Java Map界的王者?
185 2
|
4月前
|
数据采集 缓存 Java
Python vs Java:爬虫任务中的效率比较
Python vs Java:爬虫任务中的效率比较
|
12天前
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
42 0
探索Java动态代理的奥秘:JDK vs CGLIB
|
1月前
|
Java 程序员
Java 排序神器:Comparable 和 Comparator 该怎么选?
嗨,大家好,我是小米!今天和大家聊一聊Java社招面试中常考的经典问题——Comparable和Comparator的区别。Comparable定义对象的自然排序,适用于单一固定的排序规则;Comparator则是策略接口,用于定义自定义排序规则,适用于多样化或多变的排序需求。掌握这两者的区别是理解Java排序机制的基础,也是面试中的加分题。结合实际项目场景深入探讨它们的应用,能更好地打动面试官。如果你觉得有帮助,欢迎点赞、收藏、分享,期待你的一键三连!我们下期见~ 我是小米,一个喜欢分享技术的程序员,关注我的微信公众号“软件求生”,获取更多技术干货!
46 20
|
2月前
|
存储 缓存 Oracle
Java线程池,白话文vs八股文,原来是这么回事!
本文介绍了Java线程池的原理、实现方式及相关参数。首先,通过类比公司员工的方式解释了线程池的核心概念,如核心线程、最大线程数、任务队列和拒绝策略。接着,详细描述了线程池的任务处理流程,并提供了使用`ThreadPoolExecutor`和`Executors`创建线程池的代码示例,强调了`ThreadPoolExecutor`的灵活性和`Executors`的局限性。最后,总结了线程池的相关参数及不同类型的线程池实现,并附带常见面试题及其解答,帮助读者全面理解线程池的应用场景和优化方法。
56 4
|
4月前
|
安全 Java 程序员
Java集合之战:ArrayList vs LinkedList,谁才是你的最佳选择?
本文介绍了 Java 中常用的两个集合类 ArrayList 和 LinkedList,分析了它们的底层实现、特点及适用场景。ArrayList 基于数组,适合频繁查询;LinkedList 基于链表,适合频繁增删。文章还讨论了如何实现线程安全,推荐使用 CopyOnWriteArrayList 来提升性能。希望帮助读者选择合适的数据结构,写出更高效的代码。
175 3
|
6月前
|
Java C++ 开发者
if-else VS switch:谁才是Java条件判断的王者?
if-else VS switch:谁才是Java条件判断的王者?
64 3
|
6月前
|
传感器 C# 监控
硬件交互新体验:WPF与传感器的完美结合——从初始化串行端口到读取温度数据,一步步教你打造实时监控的智能应用
【8月更文挑战第31天】本文通过详细教程,指导Windows Presentation Foundation (WPF) 开发者如何读取并处理温度传感器数据,增强应用程序的功能性和用户体验。首先,通过`.NET Framework`的`Serial Port`类实现与传感器的串行通信;接着,创建WPF界面显示实时数据;最后,提供示例代码说明如何初始化串行端口及读取数据。无论哪种传感器,只要支持串行通信,均可采用类似方法集成到WPF应用中。适合希望掌握硬件交互技术的WPF开发者参考。
107 0
|
6月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
478 0
|
6月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
401 0