Java 中的对象,正常情况下,只能进行 = 或 != 比较。不能使用 > 或 < 的比较,但是在开发场景中,我们需要对多个对象进行排序,这就需要比较对象的大小。此时我们如何实现呢?java为我们提供了两个接口,使用两个接口中的任何一个: Comparable 或 Comparator 即可实现对象的比较大小!
在 Java 中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。
Java 实现对象排序的方式有两种:
1.Comparable 接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
2.实现 Comparable 的类必须实现 compareTo (Object obj)方法,两个对象即通过 compareTo (Object obj)方法的返回值来比较大小。如果当前对象 this 大于形参对象 obj ,则返回正整数,如果当前对象 this 小于形参对象 obj ,则返回负整数,如果当前对象 this 等于形参对象 obj ,则返回零。
3.实现 Comparable 接口的对象数组可以通过 Collections.sort 或Arrays.sort 进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
注:像 String 、包装类等实现了 Comparable 接口,重写了 compareTo(obj) 方法,进行了从小到大的排列!
案例一:对字符串数组进行排序
import java.util.Arrays; public class ComparableTest { public static void main(String[] args) { String[] arr = new String[]{"aniu","tom","tony","lisa"}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } }
这是因为我们的String实现了Comparable接口,并对compareTo方法进行了重写!
案例二:对自定义对象进行排序
此时我们要将这个对象实现Comparable接口,然后重写compareTo方法。
package 比较器; import java.util.Arrays; public class ComparableDemo { public static void main(String[] args) { Books[] book = new Books[4]; book[0] = new Books("The Beautiful and the Damned",68); book[1] = new Books("Where Angels Fear to Tread",45); book[2] = new Books("These Lovers Fled Away",35); book[3] = new Books("The Left Hand of Darkness",58); Arrays.sort(book); for(Books item:book){ System.out.println(item.toString()); } //System.out.println(Arrays.toString(book)); } } class Books implements Comparable{ String name; double price; public Books(String name, double price) { this.name = name; this.price = price; } //重写compareTo @Override public int compareTo(Object o) { //按照图书价格从小到大排序 if (o instanceof Books){ Books b = (Books) o; if(this.price>b.price){ return 1; }else if(this.price<b.price) { return -1; }else{ return 0; } } throw new RuntimeException("传入的数据类型不一致!"); } //重写 toString @Override public String toString() { return "Books{" + "name='" + name + '\'' + ", price=" + price + '}'; } }
这样写是从小到大排,如果要从大到小排,则需要将return值反过来!
1.当元素的类型没有实现 java.lang.Comparable 接口而又不方便修改代码,或者实现了 java.lang.Comparable 接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排序的比较。
2.重写 compare(Object o1,Object o2) 方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示
o1小于o2。
3.可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort ),从而允许在排序顺序上实现精确控制。
4.还可以使用 Comparator 来控制某些数据结构(如有序 set 或有序映射)的顺序,或者为那些没有自然顺序的对象 colection 提供排序。
案例:对自定义对象进行排序
package 比较器; import java.util.Arrays; import java.util.Comparator; public class ComparatorDemo { public static void main(String[] args) { Book[] book = new Book[4]; book[0] = new Book("The Beautiful and the Damned",68); book[1] = new Book("Where Angels Fear to Tread",45); book[2] = new Book("These Lovers Fled Away",35); book[3] = new Book("The Left Hand of Darkness",58); Arrays.sort(book, new Comparator(){ //按照价格从大到小排 @Override public int compare(Object o1, Object o2) { if(o1 instanceof Book && o2 instanceof Book){ Book b1 = (Book)o1; Book b2 = (Book)o2; return -Double.compare(b1.price,b2.price); //这里我们直接调用Double的compare方法 } throw new RuntimeException("传入的数据类型不一致!"); } }); for(Book item:book){ System.out.println(item.toString()); } //System.out.println(Arrays.toString(book)); } } class Book{ String name; double price; public Book(String name, double price) { this.name = name; this.price = price; } //重写 toString @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", price=" + price + '}'; } }
可以从代码看到,这里这里我们直接调用Double的compare方法进行了比较,不用像上面的案例一样手写了,当然我们也可以用comparTo方法,因为上面提到了,包装类也实现了Comparable接口,但Double重写的comparTo方法底层依旧是compare方法!因为是从大到小排,所以在Double前加个负号!
Comparable 接口的方式一旦一定,保证 Comparable 接口实现类的对象在任何位置都可以比较大小 ,而 Comparator 接口属于临时性的比较。
再者一个很直观的是Comparable是在自定义类中将比较规则在类中写死了的,而Comparator则比较灵活,在比较时定义比较规则,看起来灵活一点!