跳至主要內容

排序

chanchaw大约 4 分钟languagejava

实体类实现 compareTo

@Data
public class UserDTO implements Comparable<UserDTO> {
    private String name;
    private Integer age;
    
    public UserDTO(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public int compareTo(UserDTO userDTO) {
        //重写compareTo方法,按照年龄升序排序。若要降序只需要修改相减的顺序即可
        //升序
        //return this.age - userDTO.getAge();
        //降序
        return userDTO.getAge() - this.age;
    }
}
//测试方法
public static void main(String[] args) {
    List<UserDTO> list = new ArrayList<>();
    list.add(new UserDTO("西施",18));
    list.add(new UserDTO("王昭君",16));
    list.add(new UserDTO("杨昭君",20));
    list.add(new UserDTO("貂蝉",24));
    list.add(new UserDTO("猪八戒",5));
    Collections.sort(list);
    System.err.println(list);
}

//升序打印结果为:
[UserDTO(name=猪八戒, age=5), UserDTO(name=王昭君, age=16), UserDTO(name=西施, age=18), UserDTO(name=杨昭君, age=20), UserDTO(name=貂蝉, age=24)]
//降序序打印结果为:
[UserDTO(name=貂蝉, age=24), UserDTO(name=杨昭君, age=20), UserDTO(name=西施, age=18), UserDTO(name=王昭君, age=16), UserDTO(name=猪八戒, age=5)]

Lambda 表达式排序

public static void main(String[] args) {
        List<UserDTO> list = new ArrayList<>();
        list.add(new UserDTO("西施", 18));
        list.add(new UserDTO("王昭君", 16));
        list.add(new UserDTO("杨昭君", 20));
        list.add(new UserDTO("貂蝉", 24));
        list.add(new UserDTO("猪八戒", 5));
        Collections.sort(list, new Comparator<UserDTO>() {
            @Override
            public int compare(UserDTO o1, UserDTO o2) {
                //第一个参数属性 - 第二个参数属性 = 升序排序
                //第二个参数属性 - 第一个参数属性 = 降序排序
                int num = o2.getAge() - o1.getAge();
                if (num > 0) {
                    return 1;
                } else if (num < 0) {
                    return -1;
                }
                return 0;
            }
        });
        System.err.println(list);
    }
    //打印结果-降序
    [UserDTO(name=貂蝉, age=24), UserDTO(name=杨昭君, age=20), UserDTO(name=西施, age=18), UserDTO(name=王昭君, age=16), 		 UserDTO(name=猪八戒, age=5)]

// 也可以直接使用 List 对象的 sort 方法
list.sort(new Comparator<UserDTO>(){
  @Override
  public int compare(UserDTO o1,UserDTO o2){
    //TODO:xxxxx
    return 0;
  }
})
    
// 如果 JDK在8以及以上可以使用 lambda 表达式简化写法
// 使用 Lambda 表达式按照 level 升序排序
Collections.sort(mapList, (o1, o2) -> o1.get("level").compareTo(o2.get("level")));
// 或者使用更简洁的方式
mapList.sort(Comparator.comparing(m -> m.get("level")));

多属性排序

多属性排序中不可将多个属性对比的结果相加后排序,而应该是层层递进对比多属性后排序。

实体类

private class Person {
    private String name;
    private int gender;
    private int age;
    private int height;
    
    public Person(String name, int gender, int age, int height) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.height = height;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getGender() {
        return gender;
    }
    
    public void setGender(int gender) {
        this.gender = gender;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public int getHeight() {
        return height;
    }
    
    public void setHeight(int height) {
        this.height = height;
    }
    
    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", gender=" + gender +
            ", age=" + age +
            ", height=" + height +
            '}';
    }
    }

测试用数据

List<Person> ps = new ArrayList<>();
ps.add(new Person("Alice",0,11,165));
ps.add(new Person("Tom",1,99,178));
ps.add(new Person("Jerry",1,22,199));
ps.add(new Person("Alex",1,22,165));
ps.add(new Person("Luci",0,9,112));
ps.add(new Person("Anni",0,9,101));

反例

分别对比每个属性,将多个对比结果相加进行排序

public void test02(){
        List<Person> ps = new ArrayList<>();
        ps.add(new Person("Alice",0,11,165));
        ps.add(new Person("Tom",1,99,178));
        ps.add(new Person("Jerry",1,22,199));
        ps.add(new Person("Alex",1,22,165));
        ps.add(new Person("Luci",0,9,112));
        ps.add(new Person("Anni",0,9,101));

        // 多属性排序:性别(0在前)、年龄(升序)、身高(升序)
        ps.sort(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int ret = o1.getGender()-o2.getGender();
                int order1 = 0;// gender比较结果
                int order2 = 0;// age比较结果
                int order3 = 0;// height比较结果

                if(ret > 0) order1 = 1;
                else if(ret < 0) order1 = -1;
                else order1 = 0;

                ret = o1.getAge() - o2.getAge();
                if(ret > 0) order2 = 1;
                else if(ret < 0) order2 = -1;
                else order2 = 0;

                ret = o1.getHeight() - o2.getHeight();
                if(ret > 0) order3 = 1;
                else if(ret < 0) order3 = -1;
                else order3 = 0;

                return order1 + order2 + order3;
            }
        });
}

多属性渐进排序

多个属性要递进对比后排序

List<Person> ps = new ArrayList<>();
ps.add(new Person("Alice",0,11,165));
ps.add(new Person("Tom",1,99,178));
ps.add(new Person("Jerry",1,22,199));
ps.add(new Person("Alex",1,22,165));
ps.add(new Person("Luci",0,9,112));
ps.add(new Person("Anni",0,9,101));

ps.sort(new Comparator<Person>() {
    @Override
    public int compare(Person o1, Person o2) {
        int ret1 = o1.getGender()-o2.getGender();
        int ret2 = o1.getAge()-o2.getAge();
        int ret3 = o1.getHeight()-o2.getHeight();

        if(ret1 == 0)// 性别相同,按照年龄排序
            if(ret2 == 0)// 性别、年龄都相同则按照身高排序
                if(ret3 == 0) return 0;
        else return ret3 > 0 ? 1 : -1;
        else return ret2 > 0 ? 1 : -1;
        else return ret1 > 0 ? 1 : -1;
    }
});

Lambda 链式排序

    private void compare03(List<Person> list){
        list = list.stream().sorted(Comparator.comparing(Person::getGender,(int1,int2) -> {
                int ret = int1 - int2;
                if(ret == 0) return 0;
                else return ret > 0 ? 1 : -1;
            }).thenComparing(Person::getAge,(a1,a2) -> {
                int ret = a1 - a2;
                if(ret == 0) return 0;
                else return ret > 0 ? 1 : -1;
            }).thenComparing(Person::getHeight,(a1,a2) -> {
                int ret = a1 - a2;
                if(ret == 0) return 0;
                else return ret > 0 ? 1 : -1;
            })
        ).collect(Collectors.toList());

        System.out.println(list);
    }