简单介绍Java中Comparable和Comparator

转载自 简单介绍Java中Comparable和Comparator

Comparable 和 Comparator是Java核心API提供的两个接口,从它们的名字中,我们大致可以猜到它们用来做对象之间的比较的。但它们到底怎么用,它们之间有又哪些差别呢?下面有两个例子可以很好的回答这个问题。下面的例子用来比较HDTV的大小。看完下面的代码,相信对于如何使用ComparableComparator会有一个更加清晰的认识。

Comparable

一个实现了Comparable接口的类,可以让其自身的对象和其他对象进行比较。也就是说,同一个类的两个对象之间要想比较,对应的类就要实现Comparable接口,并实现compareTo()方法,代码如下:

class HDTV implements Comparable<HDTV> {private int size;private String brand;public HDTV(int size, String brand) {this.size = size;this.brand = brand;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}@Overridepublic int compareTo(HDTV tv) {if (this.getSize() > tv.getSize())return 1;else if (this.getSize() < tv.getSize())return -1;elsereturn 0;}
}public class Main {public static void main(String[] args) {HDTV tv1 = new HDTV(55, "Samsung");HDTV tv2 = new HDTV(60, "Sony");if (tv1.compareTo(tv2) > 0) {System.out.println(tv1.getBrand() + " is better.");} else {System.out.println(tv2.getBrand() + " is better.");}}
}

输出结果:

Sony is better.

Comparator

在一些情况下,你不希望修改一个原有的类,但是你还想让他可以比较,Comparator接口可以实现这样的功能。通过使用Comparator接口,你可以针对其中特定的属性/字段来进行比较。比如,当我们要比较两个人的时候,我可能通过年龄比较、也可能通过身高比较。这种情况使用Comparable就无法实现(因为要实现Comparable接口,其中的compareTo方法只能有一个,无法实现多种比较)。

通过实现Comparator接口同样要重写一个方法:compare()。接下来的例子就通过这种方式来比较HDTV的大小。其实Comparator通常用于排序。Java中的CollectionsArrays中都包含排序的sort方法,该方法可以接收一个Comparator的实例(比较器)来进行排序。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;class HDTV {private int size;private String brand;public HDTV(int size, String brand) {this.size = size;this.brand = brand;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}
}class SizeComparator implements Comparator<HDTV> {@Overridepublic int compare(HDTV tv1, HDTV tv2) {int tv1Size = tv1.getSize();int tv2Size = tv2.getSize();if (tv1Size > tv2Size) {return 1;} else if (tv1Size < tv2Size) {return -1;} else {return 0;}}
}public class Main {public static void main(String[] args) {HDTV tv1 = new HDTV(55, "Samsung");HDTV tv2 = new HDTV(60, "Sony");HDTV tv3 = new HDTV(42, "Panasonic");ArrayList<HDTV> al = new ArrayList<HDTV>();al.add(tv1);al.add(tv2);al.add(tv3);Collections.sort(al, new SizeComparator());for (HDTV a : al) {System.out.println(a.getBrand());}}
}

输出结果:

Panasonic
Samsung
Sony

以上代码就实现了通过自定义一个比较器(Comparator)来实现对一个列表进行排序。

我们也经常会使用Collections.reverseOrder()来获取一个倒序的Comparator。例如:

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(3);
al.add(1);
al.add(2);
System.out.println(al);
Collections.sort(al);
System.out.println(al);Comparator<Integer> comparator = Collections.reverseOrder();
Collections.sort(al,comparator);
System.out.println(al);

输出结果:

[3,1,2]
[1,2,3]
[3,2,1]

如何选择

简单来说,一个类如果实现Comparable接口,那么他就具有了可比较性,意思就是说它的实例之间相互直接可以进行比较。

通常在两种情况下会定义一个实现Comparator类。

1、如上面的例子一样,可以把一个Comparator的子类传递给Collections.sort()Arrays.sort()等方法,用于自定义排序规则。

2、用于初始化特定的数据结构。常见的有可排序的Set(TreeSet)和可排序的Map(TreeMap

下面通过这两种方式分别创建TreeSet

使用Comparator创建TreeSet

class Dog {int size;Dog(int s) {size = s;}
}class SizeComparator implements Comparator<Dog> {@Overridepublic int compare(Dog d1, Dog d2) {return d1.size - d2.size;}
}public class ImpComparable {public static void main(String[] args) {TreeSet<Dog> d = new TreeSet<Dog>(new SizeComparator()); // pass comparatord.add(new Dog(1));d.add(new Dog(2));d.add(new Dog(1));}
}

这里使用的就是Comparator的第二种用法,定义一个Comparator的子类,重写compare方法。然后在定义HashSet的时候,把这个类的实例传递给其构造函数。这样,再使用add方法向HashSet中增加元素的时候,就会按照刚刚定义的那个比较器的逻辑进行排序。

使用Comparable创建TreeSet

class Dog implements Comparable<Dog>{int size;Dog(int s) {size = s;}@Overridepublic int compareTo(Dog o) {return o.size - this.size;}
}public class ImpComparable {public static void main(String[] args) {TreeSet<Dog> d = new TreeSet<Dog>();d.add(new Dog(1));d.add(new Dog(2));d.add(new Dog(1));}
}

这里,定义TreeSet的时候并没有传入一个比较器。但是使用add方法向HashSet中增加的对象是一个实现了Comparable的类的实例。所以,也能实现排序功能。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329813.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring-kafka整合:KafkaTemplate-kafka模板类介绍

【README】 1&#xff0c;本文主要关注 KafkaTemplate的重点方法&#xff0c;并非全部方法&#xff1b; 2&#xff0c;KafkaTemplate 底层依赖于 DefaultKafkaProducerFactory &#xff0c; 关于 DefaultKafkaProducerFactory 的介绍&#xff0c;refer2 spring-kafka整合:…

安卓 on a null object reference_详解Object.prototype.__proto__

Object.prototype 的 __proto__ 属性是一个访问器属性(一个getter函数和一个setter函数), 暴露了通过它访问的对象的内部[[Prototype]] (一个对象或 null)。使用__proto__是有争议的&#xff0c;也不鼓励使用它。因为它从来没有被包括在EcmaScript语言规范中&#xff0c;但是现…

【SpringBoot】服务器JVM远程调试

目的 当系统部署到测试环境服务器时&#xff0c;难免会遇到bug。这个时候如果能远程调试&#xff0c;那么能够大大提高我们的生产效率&#xff0c;快速完成服务调试&#xff0c;最快发布生产环境。&#xff08;领导好评不就到手了&#xff09; 准备 Idea&#xff08;Java最好…

图说:为什么Java中的字符串被定义为不可变的

转载自 图说&#xff1a;为什么Java中的字符串被定义为不可变的字符串&#xff0c;想必大家最熟悉不过了&#xff0c;通常我们在代码中有几种方式可以创建字符串&#xff0c;比如&#xff1a;String s "Hollis";这时&#xff0c;其实会在堆内存中创建一个字符串对象…

值得推荐的微软技术公众号推荐

为开阔技术人眼界&#xff0c;促进技术人职业成长。小二在此诚意推荐最值得关注的微软技术公众号。平时关注推送的文章或多或少要么学到知识技能&#xff0c;要么收到一些启发&#xff0c;有利于个人成长。这些公众号为笔者个人积累&#xff0c;不一定都合大家口味&#xff0c;…

springboot:BeanPostProcessor示例及分析

【README】 1&#xff0c;本文主要分析 BeanPostProcessor 的作用&#xff0c; 开发方式&#xff1b; 2&#xff0c;BeanPostProcessor 是bean后置处理器&#xff0c; 简而言之就是bean被创建好了&#xff0c;之后如果需要对其属性进行修改&#xff0c;则 需要使用 BeanPost…

实现了某一个接口的匿名类的例子_java中的内部类内部接口详解,一文搞定

简介一般来说&#xff0c;我们创建类和接口的时候都是一个类一个文件&#xff0c;一个接口一个文件&#xff0c;但有时候为了方便或者某些特殊的原因&#xff0c;java并不介意在一个文件中写多个类和多个接口&#xff0c;这就有了我们今天要讲的内部类和内部接口。内部类先讲内…

Java 8 日期和时间解读

转载自 Java 8 日期和时间解读现在&#xff0c;一些应用程序仍然在使用java.util.Date和java.util.Calendar API和它们的类库&#xff0c;来使我们在生活中更加轻松的处理日期和时间&#xff0c;比如&#xff1a;JodaTime。然而&#xff0c;Java 8 引进的新的类库来处理日期和时…

云计算产值将超3000亿美元 亚马逊微软谷歌居三甲

腾讯科技讯 3月27日消息&#xff0c;据外电报道&#xff0c;云计算曾经主要是无法承担建造和维护基础设施的初创公司的解决方案&#xff0c;但对于管理数字业务的大型企业而言&#xff0c;云计算正快速成为省钱的管理数字业务的方式。市场调研公司IDC在上月的一份调查数据显示&…

oracle中join另一个表后会查询不出一些数据_面试必备 | 8个Hive数据仓工具面试题锦集!...

是新朋友吗&#xff1f;记得先点蓝字关注我哦&#xff5e;今日课程菜单Java全栈开发 | Web前端H5大数据开发 | 数据分析人工智能Python | 人工智能物联网进入数据时代&#xff0c;大数据技术成为互联网发展的核心要素之一。与此同时大数据开发工程师的薪资也成为行业内高薪的代…

springboot-Initializer例子及分析

【README】 1&#xff0c;本文主要编写了 初始化器例子并分析了其调用路径&#xff1b; 2&#xff0c;初始化器的执行顺序 先于 后置处理器&#xff1b; 后置处理器&#xff0c;refer2 springboot&#xff1a;BeanPostProcessor示例及分析_PacosonSWJTU的博客-CSDN博客【RE…

ASP.NET 开发人员不必担心 Node 的五大理由

哦别误会……我真的很喜欢 Node&#xff0c;而且我觉得它提出的概念和模式将在很长一段时间内&#xff0c;对服务端 Web 编程产生深远的影响。即使随着时间的推移 Node 过气了&#xff0c;我们肯定可以从下一个牛逼玩意身上或多或少的感觉到它的影响(不管好的和/或坏的)。而在这…

Spring Boot面试题

转载自 Spring Boot面试题 Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家。问题一 Spring Boot、Spring MVC 和 Spring 有什么区别&#xff1f; SpringFrameSpringFramework 最重要的特征是依赖注入。所有 SpringModules 不是依赖注入就…

synchronized原理_Java并发编程 -- synchronized保证线程安全的原理

线程安全是并发编程中的重要关注点&#xff0c;应该注意到的是&#xff0c;造成线程安全问题的主要诱因有两点&#xff0c;一是存在共享数据(也称临界资源)&#xff0c;二是存在多条线程共同操作共享数据。因此为了解决这个问题&#xff0c;我们可能需要这样一个方案&#xff0…

转:Java 7 种阻塞队列详解

转自&#xff1a; Java 7 种阻塞队列详解 - 云社区 - 腾讯云队列&#xff08;Queue&#xff09;是一种经常使用的集合。Queue 实际上是实现了一个先进先出&#xff08;FIFO&#xff1a;First In First Out&#xff09;的有序表。和 List、Set ...https://cloud.tencent.com/de…

微软Build 2016前瞻:让开发者编写能畅行所有设备的app

本周三&#xff0c;5000名软件开发者将齐聚旧金山莫斯康展览中心参加微软公司年度开发者大会&#xff08;Build 2016&#xff09;&#xff0c;和往年一样&#xff0c;微软在大会上发布了一系列新的技术支持。 据透露&#xff0c;微软将会让开发人员编写可以在任何Windows设备上…

XSS的那些事儿

转载自 XSS的那些事儿XSS是什么XSS&#xff0c;Cross-site scripting&#xff0c;跨站脚本攻击&#xff0c;为了区分与CSS&#xff0c;起名为XSS。黑客利用网站的漏洞&#xff0c;通过代码注入的方式将一些包含了恶意攻击脚本程序注入到网页中&#xff0c;企图在用户加载网页时…

js 时间戳转换成时间_JavaScript 时间戳转成日期格式

我们在开发中经常需要把时间戳转化成日期格式&#xff0c;但 JavaScript 本身自带的 Date 方法并不像 PHP date 的那么强大。因此&#xff0c;我们就需要自己动手写一个方法。首先我们要先了解下需要用到的 JavaScript 自带的 Date 对象的方法&#xff1a;getDate&#xff1a;获…

java阻塞队列小结

【README】 1&#xff0c;本文介绍了java的7个阻塞队列&#xff1b; 2&#xff0c;阻塞队列的作用 做缓冲作用&#xff0c;如缓冲kafka消息&#xff0c;而不是直接发送给kafka&#xff0c;减少kafka集群的压力&#xff1b;【1】阻塞队列 BlockingQueue 概述 1&#xff0c;队…

来自.NET FM的感谢信

掐指一算&#xff0c;我们的播客 .NET FM 已经上线一周了&#xff01;&#xff01;&#xff01;不过瞅下节节攀升的流量&#xff0c;二位主播一边感叹 .NET 中文社区的热情&#xff0c;一边摸了摸瘪下去的荷包&#xff1a; • 首日访问 > 2000人次 • 五日访问 > 5000人次…