学了这么长时间的集合,是否会对这三大集合进行排序呢?
首先,了解一下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的方式
package sort.list;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/** * @ClassName Demo2 * @Description: 按照User的年龄进行排序 * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/13 16:34 * @Version v1.0 */
public class Demo2 {
    @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的方式
package sort.list;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/** * @ClassName Demo2 * @Description: 按照User的年龄进行排序 * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/13 16:34 * @Version v1.0 */
public class Demo2 {
    @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. 首先使用Set集合(Set集合不允许出现相同的数据,即数据唯一,TreeSet(使用该类添加自定义的实体类时,要么实现可排序接口,要么自定义比较器)这里需要知道TreeSet的存储结构数据是排好序的。
2. 用户Person实现equals(供用户调用)和hashcode方法(在进行数据add的时候,默认调用hashcode方法)
3. hashcode通过age计算hash值,这样保证了数据的唯一性
4. 排序的话两种实现方式
	1. Person实现可排序接口Comparable
	2. 创建集合时指定比较器

代码体现:

package sort.set;

import org.junit.Test;

import java.util.*;

/** * @ClassName SetToList * @Description: 途牛面试题 * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/13 21:20 * @Version v1.0 */
public class SetToList {

    @Test
    public void test(){
        Set<Person> set = new TreeSet<>(new Comparator<Person>() {
            /** * 原先的排序方式失效(升序) * @param o1 * @param o2 * @return */
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();// 降序
            }
        });
        Person person1 = new Person("zhangsan" ,11);
        Person person2 = new Person("lisi" ,14);
        Person person3 = new Person("wangwu" ,13);
        Person person4 = new Person("lisi" ,13);

        set.add(person1);
        set.add(person2);
        set.add(person3);
        set.add(person4);

        System.out.println(set.size());
        System.out.println(set);

    }
}

class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = 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;
    }

    /** * 重写equals和hashCode方法 * 判断是否是一个对象 * (途牛面试题目,当时真的不会做) * 题目:现在存在这么个需求,就是对用户进行排序操作(升序降序都实现),前提是不能存在相同年龄的用户(当然我觉得这是不合理的) * 在进行用户添加的时候,相同年龄不再进行添加。 * 解决思路: * 首先使用Set集合(Set集合不允许出现相同的数据,即数据唯一,TreeSet(使用该类添加自定义的实体类时,要么实现可排序接口,要么自定义比较器) 数据是排序的) * 用户Person实现equals(供用户调用)和hashcode方法(在进行数据add的时候,默认调用hashcode方法) * hashcode通过age计算hash值 * 这样保证了数据的唯一性 * 排序的话两种实现方式 * 1. Person实现可排序接口Comparable * 2. 创建集合时指定比较器 * @param o * @return */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!(o instanceof Person))
            return false;
        Person person = (Person) o;
        return person.age == this.age;
    }

    /** * 对象相同的话,哈希值一定相同 * 对象不相同的话,哈希值不一定不相同(存在哈希碰撞) * 依靠这个性质判断对象是否相同 * 供散列表进行调用 HashSet HashMap... * @return */
    @Override
    public int hashCode() {
        return Objects.hash(age);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
	/* @Override public int compareTo(Person o) { return this.age - o.age; // 升序 } */
}

Map

题目:按照水果的个数进行排序
直接上代码(还可以使用List进行实现,即针对List进行排序再转换,这里直接使用TreeSet,TreeMap也可以实现):

package sort.map;

import org.junit.Test;

import java.util.*;

/** * @ClassName MapSort * @Description: 对Map进行排序 * @Author 田清波 * @Mail tqb820965236@163.com * @Date 2019/8/15 9:02 * @Version v1.0 */
public class MapSort {
    @Test
    public void test(){
        HashMap<Fruit, Integer> map = new HashMap<>();
        Fruit fruit1 = new Fruit("苹果");
        Fruit fruit2 = new Fruit("草莓");
        Fruit fruit3 = new Fruit("梨");
        Fruit fruit4 = new Fruit("西瓜");
        Fruit fruit5 = new Fruit("香蕉");

        map.put(fruit1, 9);
        map.put(fruit2, 2);
        map.put(fruit3, 8);
        map.put(fruit4, 5);
        map.put(fruit5, 1);

        Map<Fruit, Integer> sort = sort(map);
        Set<Map.Entry<Fruit, Integer>> entries = sort.entrySet();
        for (Map.Entry<Fruit, Integer> entry : entries){
            System.out.println(entry.getKey() + " " + entry.getValue());
        }
    }

    public Map<Fruit, Integer> sort(Map<Fruit, Integer> map){
        /** * 将Map转为Set */
        Set<Map.Entry<Fruit, Integer>> entries = map.entrySet();
        TreeSet<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();
            }
        });
        /** * 向TreeSet中添加数据 */
        for (Map.Entry<Fruit, Integer> entry : entries){
            set.add(entry);
        }
        /** * 将Set转为LinkHashMap(有序)返回 */
        LinkedHashMap<Fruit, Integer> resMap = new LinkedHashMap<>();
        for (Map.Entry<Fruit, Integer> entry : set){
            resMap.put(entry.getKey(), entry.getValue());
        }
        return resMap;
    }
}

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 + '\'' +
                '}';
    }
}