java集合的排序

 2022-09-06
原文地址:https://blog.csdn.net/fgfhgk/article/details/119090306

1.集合排序方式

在集合框架出现,对于实现集合排序,JDK推出了集合排序的接口Comparable(自然排序)合Comparator(比较器排序)用于集合的排序(该集合为单列集合Collection)。java.util.Collections工具类也可以实现集合排序,它可以实现List集合排序,在其中也可以使用上面的接口。

注:在Collections之前是不能直接对List集合进行排序的,只能通过TreeSet进行排序。

1.1.Comparable排序(自然排序)

1、创建实体类实现Comparable接口,实现其comparaTo(T t)方法

    public class Student implements Comparable<Student>{
    
        private int sno;
        private String sname;
        private String sex;
        private String major;
        private Date birth;
        private double score;
    
        public Student(int sno, String sname, String sex, String major, Date birth, double score) {
            this.sno = sno;
            this.sname = sname;
            this.sex = sex;
            this.major = major;
            this.birth = birth;
            this.score = score;
        }
    
        /**
         *   自然排序的比较方法
         */
        @Override
        public int compareTo(Student s) {
            return this.sname.compareTo(s.getSname());
        }
    
    	//setter/getter
        //toString
    
    }

2、创建集合,实现排序(该集合是针对TreeSet集合,因为TreeSet集合内部实现了排序功能)

    //基于数组生成List集合
    List<Student> list = Arrays.asList(
        new Student(1002,"jack","男","挖掘机专修",new Date(),88),
        new Student(1005,"rose","女","挖掘机专修",new Date(),55),
        new Student(1006,"lily","男","挖掘机专修",new Date(),59),
        new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
        new Student(1003,"jack","男","挖掘机专修",new Date(),39),
        new Student(1011,"tom","男","挖掘机专修",new Date(),59),
        new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
        new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
        new Student(1012,"admin","男","挖掘机专修",new Date(),99),
        new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
        new Student(1007,"ase","男","挖掘机专修",new Date(),32),
        new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
    );
    //将List集合转换为Set
    Set<Student> set = new TreeSet<>(list);
    for (Student s : set) {
        System.out.println(s);
    }

1.2.Comparator排序(比较器排序)

1、创建用于比较排序的实体类

    public class Student{
    
        private int sno;
        private String sname;
        private String sex;
        private String major;
        private Date birth;
        private double score;
    
        //构造器
    	//setter/getter
        //toString
    
    }

2、创建排序比较器对象

. 通过匿名内部类实现:

    List<Student> list = Arrays.asList(
        new Student(1002,"jack","男","挖掘机专修",new Date(),88),
        new Student(1005,"rose","女","挖掘机专修",new Date(),55),
        new Student(1006,"lily","男","挖掘机专修",new Date(),59),
        new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
        new Student(1003,"jack","男","挖掘机专修",new Date(),39),
        new Student(1011,"tom","男","挖掘机专修",new Date(),59),
        new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
        new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
        new Student(1012,"admin","男","挖掘机专修",new Date(),99),
        new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
        new Student(1007,"ase","男","挖掘机专修",new Date(),32),
        new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
    );
    //排序(使用匿名内部类)
    Collections.sort(list, new Comparator<Student>() {
        @Override
        public int compare(Student s1, Student s2) {
            return s1.getSname().compareTo(s2.getSname());
        }
    });
    
    for (Student s : list) {
        System.out.println(s);
    }

通过自定义排序类实现Comparator接口(该方式可以实现更好的排序扩展性)

创建单独排序类:

    public class StudentComparator implements Comparator<Student> {
        //用于排序的字段 sno,sname,score,birth
        private String field;
    
        public StudentComparator(String field) {
            this.field = field;
        }
    
        @Override
        public int compare(Student s1, Student s2) {
            switch (field){
                case "sno":
                    //按学号排序
                    return s1.getSno() - s2.getSno();
                case "sname":
                    //按姓名排序
                    return s1.getSname().compareTo(s2.getSname());
                case "score":
                    //按学分排序
                    return (int)(s2.getScore() - s1.getScore());
                case "birth":
                    //按生日排序
                    return s1.getBirth().compareTo(s2.getBirth());
                default:
                    return 0;
            }
        }
    
    }

排序实现:

    public class TestStu {
    
        public static void main(String[] args) {
    
            List<Student> list = Arrays.asList(
                    new Student(1002,"jack","男","挖掘机专修",new Date(),88),
                    new Student(1005,"rose","女","挖掘机专修",new Date(),55),
                    new Student(1006,"lily","男","挖掘机专修",new Date(),59),
                    new Student(1001,"lucy","男","挖掘机专修",new Date(),44),
                    new Student(1003,"jack","男","挖掘机专修",new Date(),39),
                    new Student(1011,"tom","男","挖掘机专修",new Date(),59),
                    new Student(1004,"bobo","男","挖掘机专修",new Date(),89),
                    new Student(1008,"aricle","男","挖掘机专修",new Date(),59),
                    new Student(1012,"admin","男","挖掘机专修",new Date(),99),
                    new Student(1010,"softeem","男","挖掘机专修",new Date(),46),
                    new Student(1007,"ase","男","挖掘机专修",new Date(),32),
                    new Student(1009,"jojo","男","挖掘机专修",new Date(),10)
            );
    
    //        默认自然排序规则排序(Comparable)
    //        Collections.sort(list);
            
            //使用匿名内部类方式
    //        Collections.sort(list, new Comparator<Student>() {
    //            @Override
    //            public int compare(Student s1, Student s2) {
    //                return s1.getSname().compareTo(s2.getSname());
    //            }
    //        });
    
            //使用独立比较器
            Collections.sort(list,new StudentComparator("score"));
    
            for (Student s : list) {
                System.out.println(s);
            }
    
        }
    }

3、Collections类

该类是实现集合排序的工具类,可以对List集合进行排序,在排序过程中还是依赖于Comparable,Compatator接口,该类除了排序还有许多其他功能对集合元素:查找, 排序 ,洗牌,转换,拷贝,查找最大值/最小值,集合反转,安全集合的获取等一系列静态方法。

1、关于排序

  • 依赖于Comparable
      Collections.sort(List<T> list);
  • 依赖于Comparator
    
            
            //使用匿名内部类方式
           Collections.sort(list, new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    return s1.getSname().compareTo(s2.getSname());
                }
            });
    //使用独立比较器
            Collections.sort(list,new StudentComparator("score"));
    
            for (Student s : list) {
                System.out.println(s);
            }
    
        }
    }

4、 扩展:中文排序

对于排序的需求我们已经可以使用如上的两个接口实现了,但是对于一些特殊的排序需求,例如:中文排序,JDK并没有提供很合适的解决方案,因此这里可以借助第三方的插件pinyin4j实现。

    //将一个中文字符转换为一个包含了多种读音的字符串数组
    String[] s = PinyinHelper.toHanyuPinyinStringArray('和');
    System.out.println(Arrays.toString(s));
    
    //将一个中文字符串整体抓换为汉语拼音
    String name = "苍老师";//cang1lao3shi1
    String pinyin = "";
    for (int i = 0; i < name.length(); i++) {
        pinyin += PinyinHelper.toHanyuPinyinStringArray(name.charAt(i))[0];
    }
    System.out.println(pinyin);
    
    //排序实现
    List<String> list = new ArrayList<>();
    list.add("吕布");     //lv    4
    list.add("貂蝉");     //diao  3
    list.add("ma老师");    //ma   5
    list.add("柴老师");    //chai 2
    list.add("苍老师");    //cang 1
    list.add("肖老师");    //xiao 7
    list.add("王老师");    //wang 6
    
    //实现将一个中文字符转换为汉语拼音
    
    list.sort(new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            String p1 = "";
            String p2 = "";
            //分别获取两个被比较对象的汉语拼音字符串
            for (int i = 0; i < s1.length(); i++) {
                if(String.valueOf(s1.charAt(i)).matches("^[\\u4e00-\\u9fa5]{0,}$")){
                    p1 += PinyinHelper.toHanyuPinyinStringArray(s1.charAt(i))[0];
                }
            }
            for (int i = 0; i < s2.length(); i++) {
                if(String.valueOf(s2.charAt(i)).matches("^[\\u4e00-\\u9fa5]{0,}$")) {
                    p2 += PinyinHelper.toHanyuPinyinStringArray(s2.charAt(i))[0];
                }
            }
            //实现比较
            return p1.compareTo(p2);
        }
    }