一、为什么要“新”的比较方法
Java有非常丰富的API供我们使用,比较方法也有很多种,不仅是我们在平时经常用到的equals()方法,其实很多工具类的排序方法也是基于最基础的比较的方法实现的。例如,Arrays.sort() 就与类中compareTo() 的值相关。
我们在实际开发或者写算法题时,可能要用到对象的比较。
此时,我们可以有两种办法去丰富Java所提供的方法。
二、Comparable接口的使用(自然排序)
1.像String、包装类实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象的方式
2.重写compareTo(obj)的规则:
- 如果this > obj , return 正整数
- 如果this == obj , return 0
- 如果this < obj , return 负整数
举个例子,假如我们有一个商品类,里面有一个属性是商品的价格,此时我们想用价格大小来进行排序,那么这个类需要实现Comparable接口,并且重写compareTo()方法,如果想从小到大排那按上面的顺序即可,如果要从大到小的话把return改一下就好了。下面是实现的代码:
Goods类
public class Goods implements Comparable {
private String name;
private double place;
public Goods() {
}
public Goods(String name, double place) {
this.name = name;
this.place = place;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPlace() {
return place;
}
public void setPlace(double place) {
this.place = place;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", place=" + place +
'}';
}
@Override
public int compareTo(Object o) {
if (o instanceof Goods) {
Goods good = (Goods) o;
if (place < good.place) {
return -1;
} else if (place > good.place) {
return 1;
} else {
return this.name.compareTo(good.name);//如果相等按商品名字的字典顺序进行排序
}
}
throw new RuntimeException("类型错误,无法比较");
}
}
测试方法
public void test() {
Goods[] goods = new Goods[4];
goods[0] = new Goods("lenov",4500);
goods[1] = new Goods("zhengjiuzhe",7500);
goods[2] = new Goods("macbook air",6000);
goods[3] = new Goods("dell",3000);
//sort()和compareTo()的值有关
Arrays.sort(goods);
System.out.println(Arrays.toString(goods));
}
三、Comparator类的使用(定制排序)
1.背景: 当元素的类型没有实现Comparable接口而又不方便修改代码,或者实现了Comparable接口的排序不适合当前的操作(如从大到小排),就可以使用Comparator的对象来排序
2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小 :
- 如果方法返回正整数,表示 o1 > o2
- 如果返回0,表示 o1 == o2
- 如果返回负整数,表示 o1 < o2
3.举个例子,附上一道刚遇到的算法题吧,里面就用到了这个思想
题目来源LeetCode,这题是个中等题,但难点其实是在如何重新对字符串进行排序,学会了上面的方法就豁然开朗了。
class Solution {
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> cnt = new HashMap<>();//用于统计字符串出现次数
for(int i = 0; i < words.length; i++) {
cnt.put(words[i], cnt.getOrDefault(words[i], 0) + 1);
}
List<String> list = new ArrayList<>();
for(Map.Entry<String, Integer> entry : cnt.entrySet()) {
list.add(entry.getKey());
}
//开始排序了,相同则直接用系统自带的就可以返回字典排序
//不同的话按照上面的规则,需要注意的是此次排序需要从大到小,所以是反过来的
Collections.sort(list, new Comparator<String>() {
public int compare(String word1, String word2) {
return cnt.get(word1) == cnt.get(word2) ?
word1.compareTo(word2) : cnt.get(word2) - cnt.get(word1);
}
});
return list.subList(0, k);
}
}