持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
在java中实现比较功能是很容易的。当遇到自定义类型,或比较对象不能直接进行比较,我们需要使用比较策略,通过Comparator 或 Comparable 接口即可简单实现。
可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
相同点
1.两者都是接口。
2.两者的功能都是排序。
不同点
1.Comparable在java.lang包下,Comparator在java.util包下
2.实现Comparable接口要重写compareTo方法
Comparable
对于自定义类的对象我们想要进行排序,则可以让自定义类实现Comparable接口,重写compareTo(obj)方法,指明如何排序。
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());
}
}
}
Comparator
对已经实现了Comparable接口的类想改变排序方式,只是临时用一下不想改类代码(如默认是升序,想改成降序),可以临时用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 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。
用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象。