List、Set、Map排序详解

首先,了解一下Comparator和Comparable
通常,要对一个存储在集合内的实体类进行排序时,有两种策略:1. 实体类实现Comparable接口;2. 创建集合时指定Comparator,即实现Comparator接口;
区别:称实现Comparable的实体类是可排序的,而Comparator则称为比较器
下面使用具体的代码来使用这两个接口(按照使用的集合分别进行讲解)

一、List

List中存储的是Integer等数据类型的话,直接使用Collections.sort(List<E> list)或者Collections.sort(List<E> list, Comparator<? super T> c)进行排序。这里讲的是自定义类的排序。

  1. 实现Comparable的方式
public class Demo {

    @Test
    public void test(){
        User user1 = new User("zhangsan", 23);
        User user2 = new User("lisi", 25);
        User user3 = new User("wangwu", 20);

        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);

        System.out.println("未排序:" + list);
        Collections.sort(list);
        System.out.println("已排序:" + list);
    }
}

class User implements Comparable<User>{
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(User o) {
        /** * 指定对象减去此对象 - 降序 * 此对象减去指定对象 - 升序 */
        // System.out.println(o.age - this.age);
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  1. 实现Comparator的方式
public class Demo {

    @Test
    public void test(){
        User user1 = new User("zhangsan", 23);
        User user2 = new User("lisi", 25);
        User user3 = new User("wangwu", 20);

        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);

        System.out.println("未排序:" + list);
        /** * 通过匿名内部类进行实现,即指定排序的方式 */
        Collections.sort(list, new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                /** * o2 - o1 : 降序 * o1 - o2 : 升序 */
                return o2.getAge() - o1.getAge();
            }
        });
        System.out.println("已排序:" + list);
    }
}

class User {
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {

        return age;
    }
    public void setAge(Integer age) {
        this.age = age;

    }
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

二、Set

需求:学生进行排序操作(升序降序都实现),前提是不能存在相同年龄的学生(当然我觉得这是不合理的)在进行学生添加的时候,相同年龄不再进行添加。
解决思路:

1

2

3

4

5

6

1. 首先使用Set集合(Set集合不允许出现相同的数据,即数据唯一,TreeSet(使用该类添加自定义的实体类时,要么实现可排序接口,要么自定义比较器)这里需要知道TreeSet的存储结构数据是排好序的。

2. 用户Person实现equals(供用户调用)和hashcode方法(在进行数据add的时候,默认调用hashcode方法)

3. hashcode通过age计算hash值,这样保证了数据的唯一性

4. 排序的话两种实现方式

    1. Person实现可排序接口Comparable

    2. 创建集合时指定比较器

public class Person4 {

    public static void main(String[] args) {
        Set<Person> set = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.age - o2.age;
                //return o2.age - o1.age;
            }
        });
        set.add(new Person("zhangsan" ,11));
        set.add(new Person("lisi" ,14));
        set.add(new Person("wangwu" ,13));
        set.add(new Person("lisi" ,13));
        //[Person{name='zhangsan', age=11}, Person{name='wangwu', age=13}, Person{name='lisi', age=14}]
        System.out.println(set);
    }

    static class Person {
        private String name;
        private Integer age;

        public Person() {
        }

        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public boolean equals(Object o) {
            if(this == o){
                return true;
            }if(o == null || o.getClass() != this.getClass()){
                return false;
            }if(!(o instanceof Person)){
                return false;
            }
            Person person = (Person)o;
            return person.age.equals(this.age);
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(age);
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

三、Map

题目:按照水果的个数进行排序

public class MapSort {

    public static void main(String[] args) {
        Map<Fruit, Integer> map = new HashMap<>();
        map.put(new Fruit("苹果"), 9);
        map.put(new Fruit("草莓"), 2);
        map.put(new Fruit("梨"), 8);
        map.put(new Fruit("西瓜"), 5);
        map.put(new Fruit("香蕉"), 1);

        Set<Map.Entry<Fruit,Integer>> set = new TreeSet<>(new Comparator<Map.Entry<Fruit,Integer>>() {
            @Override
            public int compare(Map.Entry<Fruit,Integer> o1, Map.Entry<Fruit,Integer> o2){
                return o1.getValue() - o2.getValue();
            }
        });

        for (Map.Entry<Fruit,Integer> entry : map.entrySet()){
            set.add(entry);
        }

        for(Map.Entry<Fruit,Integer> entry:set){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        //Fruit{name='香蕉', remark='null'}:1
        //Fruit{name='草莓', remark='null'}:2
        //Fruit{name='西瓜', remark='null'}:5
        //Fruit{name='梨', remark='null'}:8
        //Fruit{name='苹果', remark='null'}:9
    }

   static class Fruit {
        private String name;
        private String remark;

        public Fruit() {
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getRemark() {
            return remark;
        }

        public void setRemark(String remark) {
            this.remark = remark;
        }

        public Fruit(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Fruit{" +
                    "name='" + name + '\'' +
                    ", remark='" + remark + '\'' +
                    '}';
        }
    }

参考:

https://blog.nowcoder.net/n/618ef4c967424db19885b8b56114d76c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值