Java类的排序

 

目录

Java中类型的排序

Arrays和Collection重写Comparator比较器进行排序(常用)

说明:

独立写比较器Comparator

匿名类方式重写比较器

定义的类中实现Comparable接口

实例应用:LeetCode406


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][]);
    } 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值