Java中的比较器详细解析
引入的背景
我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,直接使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢?
在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。 Java实现对象排序的方式有两种:
- 自然排序:java.lang.Comparable
- 定制排序:java.util.Comparator
自然排序:java.lang.Comparable
Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
- 如果当前对象this大于形参对象obj,则返回正整数。
- 如果当前对象this小于形参对象obj,则返回负整数。
- 如果当前对象this等于形参对象obj,则返回零。
package java.lang; public interface Comparable{ int compareTo(Object obj); }
Comparable 的典型实现:(默认都是从小到大排列的)
- String:按照字符串中字符的Unicode值进行比较
- Character:按照字符的Unicode值来进行比较
- 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
- Boolean:true 对应的包装类实例大于 false 对应的包装类实例
- Date、Time等:后面的日期时间比前面的日期时间大
测试String
代码示例:
@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"); } }
运行效果:
测试自己实现comparable接口
Product类
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 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]); } }
运行效果
定制排序:java.util.Comparator
思考
- 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码(例如:一些第三方的类,你只有.class文件,没有源文件)
- 如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?(例如:我想要String按照字母从大到小的顺序排序,而不是默认的从小到大)
JDK在设计类库之初,也考虑到这种情况,所以又增加了一个java.util.Comparator接口。强行对多个对象进行整体排序的比较。
- 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
- 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
Product类
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
@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]); } }
运行效果:
按照名称进行排序的comparator
//按照名称进行排序 @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]); } }
运行效果:
到此这篇关于Java中的比较器详细解析的文章就介绍到这了,更多相关Java中的比较器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
IDEA 中使用 Big Data Tools 连接大数据组件
本文主要介绍了IDEA 中使用 Big Data Tools 连接大数据组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-05-05浅谈Java异常的Exception e中的egetMessage()和toString()方法的区别
下面小编就为大家带来一篇浅谈Java异常的Exception e中的egetMessage()和toString()方法的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-07-07
最新评论