Java 提供了两个接口来使用类的数据成员对对象进行排序:Comparable和Comparator。
Comparable
Comparable对象能够将自己与另一个对象进行比较。类本身必须实现java.lang.Comparable接口。
假设有一个Movie类,它的成员评分、名称、年份。如果希望根据年份对电影列表进行排序。可以用Movie类实现Comparable接口,重写Comparable接口的compareTo()方法。
class Movie implements Comparable<Movie> {
private double rating;
private String name;
private int year;
// Used to sort movies by year
public int compareTo(Movie m) {
return this.year - m.year;
}
// Constructor
public Movie(String nm, double rt, int yr) {
this.name = nm;
this.rating = rt;
this.year = yr;
}
// Getter methods for accessing private data
public double getRating() {
return rating;
}
public String getName() {
return name;
}
public int getYear() {
return year;
}
}
class Main {
public static void main(String[] args) {
ArrayList<Movie> list = new ArrayList<Movie>();
list.add(new Movie("Force Awakens", 8.3, 2015));
list.add(new Movie("Star Wars", 8.7, 1977));
list.add(new Movie("Empire Strikes Back", 8.8, 1980));
list.add(new Movie("Return of the Jedi", 8.4, 1983));
Collections.sort(list);
System.out.println("Movies after sorting : ");
for (Movie movie : list) {
System.out.println(movie.getName() + " " +
movie.getRating() + " " +
movie.getYear());
}
}
}
现在,假设还想按电影的评分和名称对电影进行排序。当使一个集合元素具有可比性(通过让它实现 Comparable)时,只有一次机会实现 compareTo()方法。解决方案是使用比较器。
Comparator
与Comparable不同,Comparator在要比较的元素类型之外创建的单独的类。
Collections类有第二个sort()方法,它需要Comparator。sort()方法调用compare()对对象进行排序。
要按评分比较电影,需要做 3 件事:
- 创建一个实现Comparator的类并实现compare() 方法。
- 创建Comparator类的实例。
- 调用重载的sort()方法,传入列表和实现Comparator的类的实例。
class Movie implements Comparable<Movie> {
private double rating;
private String name;
private int year;
// Used to sort movies by year
public int compareTo(Movie m) {
return this.year - m.year;
}
// Constructor
public Movie(String nm, double rt, int yr) {
this.name = nm;
this.rating = rt;
this.year = yr;
}
// Getter methods for accessing private data
public double getRating() {
return rating;
}
public String getName() {
return name;
}
public int getYear() {
return year;
}
}
// Class to compare Movies by ratings
class RatingCompare implements Comparator<Movie> {
public int compare(Movie m1, Movie m2) {
if (m1.getRating() < m2.getRating()) return -1;
if (m1.getRating() > m2.getRating()) return 1;
else return 0;
}
}
// Class to compare Movies by name
class NameCompare implements Comparator<Movie> {
public int compare(Movie m1, Movie m2) {
return m1.getName().compareTo(m2.getName());
}
}
// Driver class
class Main {
public static void main(String[] args) {
ArrayList<Movie> list = new ArrayList<Movie>();
list.add(new Movie("Force Awakens", 8.3, 2015));
list.add(new Movie("Star Wars", 8.7, 1977));
list.add(new Movie("Empire Strikes Back", 8.8, 1980));
list.add(new Movie("Return of the Jedi", 8.4, 1983));
// Sort by rating : (1) Create an object of ratingCompare
// (2) Call Collections.sort
// (3) Print Sorted list
System.out.println("Sorted by rating");
RatingCompare ratingCompare = new RatingCompare();
Collections.sort(list, ratingCompare);
for (Movie movie : list)
System.out.println(movie.getRating() + " " +
movie.getName() + " " +
movie.getYear());
// Call overloaded sort method with RatingCompare
// (Same three steps as above)
System.out.println("\nSorted by name");
NameCompare nameCompare = new NameCompare();
Collections.sort(list, nameCompare);
for (Movie movie : list)
System.out.println(movie.getName() + " " +
movie.getRating() + " " +
movie.getYear());
// Uses Comparable to sort by year
System.out.println("\nSorted by year");
Collections.sort(list);
for (Movie movie : list)
System.out.println(movie.getYear() + " " +
movie.getRating() + " " +
movie.getName() + " ");
}
}
总结
- Comparable适用于具有自然排序的对象,这意味着对象本身必须知道如何对其进行排序。例如学生人数。而Comparator接口排序是通过一个单独的类完成的。
- 从逻辑上讲,Comparable接口将“this”引用与指定的对象进行比较,Java中的Comparator比较提供的两个不同的类对象。
- 如果任何类在Java中实现Comparable接口,则可以使用Collections.sort()或Arrays.sort()方法自动对该对象的集合List或Array进行排序,并且对象将根据CompareTo方法定义的自然顺序进行排序。
- 一个基本的区别特征是,使用Comparable只能使用一个比较。然而,可以为给定类型编写多个自定义比较器,所有这些都使用对排序含义的不同解释。就像在可比较的示例中一样,只能按一个属性(即年份)进行排序,但在比较器中,也可以使用不同的属性,例如评级、姓名和年份。
总而言之,如果对象的排序需要基于自然顺序,则使用Comparable,而如果需要对不同对象的属性进行排序,则使用Java中的 Comparator。
感谢大家的支持,如有错误请指正,如需转载请标明原文出处!