目录
Arrays和Collection重写Comparator比较器进行排序(常用)
Java中类型的排序
Java中类型的排序主要有两种方式,第一种是重写Comparator<T>使用比较器进行比较,第二种是被排序的类自己继承Comparable重写compareTo方法通过自排序的方式完成排序。
其中第一种方式更常见。
主要有两种方式实现:
Arrays和Collection重写Comparator比较器进行排序(常用)
在Collections.sort(Collections, Comparator)中重写Comparator,这种方式也是最常用的方式。
说明:
1. Collections.sort(Collection,Comparator) 通常用于比较List这种Collection的子类。
2. Arrays.sort(Person[] ,Comparator ) 通常用于比较数组类型,无论是int,char或者是自定义的数组类型的数组。
3. 如果仔细看源码,可以发现Collections的排序,会先把list转成数组,然后调用Arrays进行排序。
4. Comparator中有两个对象 o1和o2 ,o1-o2 升序,o2-o1 降序。(其实源码也是根据正负号判断的,方便使用可以直接这么用)
5. 源码通常情况下使用的排序方式都是 归并排序,因此时间复杂度NlogN,空间复杂度 N,效率还蛮高的。
独立写比较器Comparator
需要排序的类型:
package compare;
public class Person {
public int age;
public String name;
Person(int age, String name) {
this.age = age;
this.name = name;
}
}
排序的比较器:
package compare;
import java.util.Comparator;
public class PersonByAge implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
// 第一个参数 - 第二个参数
// return值为负数 则顺序不变
// return值为正数 则顺序调换
return o1.age - o2.age; //升序
}
}
主函数:
public class Cmshome {
public static void main(String[] args) {
Person p1 = new Person(11, "a");
Person p2 = new Person(99, "b");
Person p3 = new Person(21, "c");
Person p4 = new Person(15, "d");
List<Person> persons = new ArrayList<>();
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println("persons原来的默认顺序如下:");
for (Person p : persons) {
System.out.println(p.toString());
}
System.out.println("------下面按 age int 类型排序-----升序-------");
Comparator<Person> ascComparatorByAge = new PersonByAge();
Collections.sort(persons, ascComparatorByAge);
for (Person p : persons) {
System.out.println(p.toString());
}
}
}
匿名类方式重写比较器
不过通常情况下,都不会在定义一个类去重写比较器,一般可以直接用匿名类(重写Comparator)完成该功能。
public class Cmshome {
public static void main(String[] args) {
Person p1 = new Person(11, "a");
Person p2 = new Person(99, "b");
Person p3 = new Person(21, "c");
Person p4 = new Person(15, "d");
List<Person> persons = new ArrayList<>();
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println("persons原来的默认顺序如下:");
for (Person p : persons) {
System.out.println(p.toString());
}
System.out.println("------下面按 age int 类型排序-----升序-------");
Collections.sort(persons, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
});
for (Person p : persons) {
System.out.println(p.toString());
}
}
}
定义的类中实现Comparable接口
在定义的时候,需要实现Comparable接口,重写compareTo这个方法。可以将this当做之前compare中的第一个参数,入参当做第二个参数。
实现的类型:
public class Car implements Comparable<Car> {
public String sign;
public int price;
public Car(String sign, int price) {
this.sign = sign;
this.price = price;
}
@Override
public int compareTo(Car o) {
//同理也可以根据sign属性排序,就不举例啦。
return this.price - o.price;
}
@Override
public String toString() {
return "Car{" + "sign='" + sign + '\'' + ", price=" + price + '}';
}
}
实现的主函数代码:
public class Cmshome {
public static void main(String[] args) {
Car car1 = new Car("ben", 1000);
Car car2 = new Car("qqq", 1);
Car car3 = new Car("bmw", 10000);
Car car4 = new Car("wow", 100);
List<Car> cars = new ArrayList<>();
cars.add(car1);
cars.add(car2);
cars.add(car3);
cars.add(car4);
System.out.println("cars原来的默认顺序如下:");
for (Car car : cars) {
System.out.println(car.toString());
}
System.out.println("------下面按 price int 类型排序--升序----------");
Collections.sort(cars);
for (Car car : cars) {
System.out.println(car.toString());
}
}
}
实例应用:LeetCode406
链接:https://leetcode-cn.com/problems/queue-reconstruction-by-height/
解决方案:
/**
* 这个题目看起来很难,但是用贪心,两次排序即可
* 例子:
* {{7,0},{4,4},{7,1},{5,0},{6,1},{5,2}}
* <p>
* 第一遍根据身高从高到低排序,如果身高一样,在根据第二个参数前边比它高的人数有多少升序
* 这样排序的好处是可以快速把大量的框架排好,之后微调即可
* {{7,0},{7,1},{6,1},{5,0},{5,2},{4,4}}
* <p>
* 第二遍排序,将第一个放好位置之后,第二个人,从前往后遍历,遍历到合适位置时,进行插入即可,因为往前找,都一定是比该值更高的人
* {{5,0},{7,0},{5,2},{6,1},{4,4},{5,2}}
*
* @param people 人的身高信息和左侧比其高的人的数量
* @return 重新排序后的返还值
*/
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] == o2[0]) {
return o1[1] - o2[1];
}
return o2[0] - o1[0];
}
});
List<int[]> lists = new ArrayList<>();
lists.add(people[0]);
for (int i = 1; i < people.length; i++) {
if (people[i][1] >= lists.size()) {
lists.add(people[i]);
} else {
lists.add(people[i][1], people[i]);
}
}
return lists.toArray(new int[people.length][]);
}