Java—Sort排序

转自:https://blog.csdn.net/whp1473/article/details/79678974

Java中Sort排序是非常常用的方法,这一章我们主要来认识一下Sort的用法和相关的实现

一、数组Sort排序

升序排序,直接使用Arrays.Sort方法,例如:

int[] array = {10, 3, 6, 1, 4, 5, 9};
//正序排序
Arrays.sort(array);//会检查数组个数大于286且连续性好就使用归并排序,若小于47使用插入排序,其余情况使用双轴快速排序
System.out.println(“升序排序:”);
for (int num : array) {
System.out.println(num);
}

降序排序,对于只输出数组的情况,可以倒叙循环访问,例如:

//倒序排序
//(1)由于不提供倒排方法,你可以倒叙输出
System.out.println(“降序输出:”);
for (int i = array.length - 1; i >= 0; i–) {
System.out.println(array[i]);
}

降序排序,对于需要使用数组 的情况,可以创建一个新的数组,然后倒叙访问赋值,例如:


 
 
  1. //(2)或者创建一个新的数组,倒叙保存到新数组
  2. int[] descArray = new int[array.length];
  3. for ( int i = 0; i < array.length; i++) {
  4. descArray[i] = array[array.length - i - 1];
  5. }
  6. System.out.println( “新数组降序输出:”);
  7. for ( int num : descArray) {
  8. System.out.println(num);
  9. }

降序排序,可以先将数组转为集合,然后使用Collections.reverse()反转集合,但是对于非引用类型,不可以使用Arrays.asList(),因为int[]会被当作一个类型,而不是数组。

所以可以使用Guava的Ints.asList()方法实现,该转换后的集合,实现了List接口的方法,直接将数组转入内部的数组变量,需要注意它并没有实现数组的操作方法,例如调用add会报错:

转换和排序例如:


 
 
  1. //(3)或者使用Guava来实现
  2. List<Integer> integersList = Ints.asList(array);
  3. Collections.reverse(integersList); //冒泡交换
  4. System.out.println( “Guava降序输出:”);
  5. for ( int num : integersList) {
  6. System.out.println(num);
  7. }

转后的集合类是Guava中的IntArrayAsList,其类UML图如下:


二、集合Sort排序—包装类

本小节主要是对jdk类库中的包装类排序,例如:Integer、String等,这些类都已经重写了Compare方法,都有默认排序规则,例如对于Integer类型会比较其包装的值类型大小,对于String类型会以长度最小字符串为基准,逐一比较相同位置字符的ASCII码大小,如果都相同则比较字符串的长度。

以Integer为例子,升序排序:


 
 
  1. //Integer集合,正序排序
  2. List<Integer> list = new ArrayList<Integer>(Arrays.asList( 10, 3, 6, 1, 4, 5, 9));
  3. Collections.sort(list);
  4. System.out.println( “集合正序排序:”);
  5. for (Integer num : list) {
  6. System.out.println(num);
  7. }

返回:


 
 
  1. 集合正序排序:
  2. 1
  3. 3
  4. 4
  5. 5
  6. 6
  7. 9
  8. 10

降序排序:


 
 
  1. //倒叙排序
  2. Comparator<Integer> reverseComparator = Collections.reverseOrder();
  3. Collections.sort(list, reverseComparator);
  4. System.out.println( “集合倒叙排序:”);
  5. for (Integer num : list) {
  6. System.out.println(num);
  7. }

返回:


 
 
  1. 集合倒叙排序:
  2. 10
  3. 9
  4. 6
  5. 5
  6. 4
  7. 3
  8. 1

三、集合Sort排序—自定义对象

除了两节所描述的情况,我们还会遇到对于自定义类排序的情况,例如我们现在有一个学生对象,想要根据年龄对其进行排序,学生类Student如下:


 
 
  1. public class Student {
  2. private String name;
  3. private Integer age;
  4. public Student(String name, Integer age) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public Integer getAge() {
  15. return age;
  16. }
  17. public void setAge(Integer age) {
  18. this.age = age;
  19. }
  20. /**
  21. * 为了更好显示数据,我们重写toString()方法.
  22. * @return 显示变量的字符串
  23. */
  24. @Override
  25. public String toString() {
  26. return “Student{” +
  27. “name=’” + name + ‘’’ +
  28. “, age=” + age +
  29. ‘}’;
  30. }
  31. }

(1) 第一种方式,是实现Comparable接口,重写接口方法。

该CompareTo()方法,如果指定的数与参数相等返回0;如果指定的数小于参数返回 -1;如果指定的数大于参数返回 1。

对于排序来讲,你可以认为当返回1时,指定的数和参数会进行交换,而非1时则不变,指定数可以当作原本的数组中靠前的数,而参数可以当作靠后的数,又因为只有靠前数大于靠后数时才返回1,所以大的会被放到后面,此时升序排序(方便记忆)。以此类推,倒序情况则相反。

升序排序,比Student类增加了Comparable接口,并实现升序排序:


 
 
  1. public class StudentAsc implements Comparable<StudentAsc> {
  2. private String name;
  3. private Integer age;
  4. public StudentAsc(String name, Integer age) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public Integer getAge() {
  15. return age;
  16. }
  17. public void setAge(Integer age) {
  18. this.age = age;
  19. }
  20. public int compareTo(StudentAsc o) {
  21. if( null == this.age) {
  22. return - 1;
  23. }
  24. if( null == o.getAge()) {
  25. return 1;
  26. }
  27. return this.age.compareTo(o.getAge());
  28. }
  29. @Override
  30. public String toString() {
  31. return “StudentAsc{” +
  32. “name=’” + name + ‘’’ +
  33. “, age=” + age +
  34. ‘}’;
  35. }
  36. }

方法调用:


 
 
  1. //正序排序,年龄为null时为小
  2. StudentAsc studentWang = new StudentAsc( “王小二”, 10);
  3. StudentAsc studentZhang = new StudentAsc( “张三”, 1);
  4. StudentAsc studentGou = new StudentAsc( “狗子”, 99);
  5. StudentAsc studentZhao = new StudentAsc( “赵六”, 40);
  6. StudentAsc studentLi = new StudentAsc( “李四”, null);
  7. List<StudentAsc> studentAscs = new ArrayList<StudentAsc>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
  8. Collections.sort(studentAscs);
  9. System.out.println( “自定义对象,升序排序:”);
  10. for(StudentAsc studentAsc : studentAscs) {
  11. System.out.println(studentAsc.toString());
  12. }

返回:


 
 
  1. 自定义对象,升序排序:
  2. Student{name= ‘李四’, age= null}
  3. Student{name= ‘张三’, age= 1}
  4. Student{name= ‘王小二’, age= 10}
  5. Student{name= ‘赵六’, age= 40}
  6. Student{name= ‘狗子’, age= 99}

降序排序,比Student类增加了Comparable接口,并实现倒序排序


 
 
  1. public class StudentDesc implements Comparable<StudentDesc> {
  2. private String name;
  3. private Integer age;
  4. public StudentDesc(String name, Integer age) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public Integer getAge() {
  15. return age;
  16. }
  17. public void setAge(Integer age) {
  18. this.age = age;
  19. }
  20. public int compare(Integer o1, Integer o2) {
  21. return o2.compareTo(o1);
  22. }
  23. public int compareTo(StudentDesc o) {
  24. if( null == this.age) {
  25. return 1;
  26. }
  27. if( null == o.getAge()) {
  28. return - 1;
  29. }
  30. return o.age.compareTo( this.getAge());
  31. }
  32. @Override
  33. public String toString() {
  34. return “StudentDesc{” +
  35. “name=’” + name + ‘’’ +
  36. “, age=” + age +
  37. ‘}’;
  38. }
  39. }

方法调用:


 
 
  1. //降叙排序,年龄为null时为最大
  2. StudentDesc studentWang = new StudentDesc( “王小二”, 10);
  3. StudentDesc studentZhang = new StudentDesc( “张三”, 1);
  4. StudentDesc studentGou = new StudentDesc( “狗子”, 99);
  5. StudentDesc studentZhao = new StudentDesc( “赵六”, 40);
  6. StudentDesc studentLi = new StudentDesc( “李四”, null);
  7. List<StudentDesc> studentAscs = new ArrayList<StudentDesc>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
  8. Collections.sort(studentAscs);
  9. System.out.println( “自定义对象,降序排序:”);
  10. for(StudentDesc studentAsc : studentAscs) {
  11. System.out.println(studentAsc.toString());
  12. }

返回:


 
 
  1. 自定义对象,降序排序:
  2. Student{name= ‘狗子’, age= 99}
  3. Student{name= ‘赵六’, age= 40}
  4. Student{name= ‘王小二’, age= 10}
  5. Student{name= ‘张三’, age= 1}
  6. Student{name= ‘李四’, age= null}

(2)第二种方式,上面实现Comparable接口的方法并不十分灵活,比如对于一个类,在不同的地方需要使用不同的排序,此时再这样做就会显的十分繁琐。因此我们可以通过Collections.sort(List<T> list, Comparator<? super T> c)方法来实现,例子中,我们使用Student类,例子如下:

升序排序:


 
 
  1. //升序排序
  2. Student studentWang = new Student( “王小二”, 10);
  3. Student studentZhang = new Student( “张三”, 1);
  4. Student studentGou = new Student( “狗子”, 99);
  5. Student studentZhao = new Student( “赵六”, 40);
  6. Student studentLi = new Student( “李四”, null);
  7. List<Student> students = new ArrayList<Student>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
  8. Collections.sort(students, new Comparator<Student>() {
  9. public int compare(Student o1, Student o2) {
  10. if( null == o1.getAge()) {
  11. return - 1;
  12. }
  13. if( null == o2.getAge()) {
  14. return 1;
  15. }
  16. return o1.getAge().compareTo(o2.getAge());
  17. }
  18. });
  19. System.out.println( “自定义对象,升序排序:”);
  20. for(Student student : students) {
  21. System.out.println(student.toString());
  22. }

返回:


 
 
  1. 自定义对象,升序排序:
  2. Student{name= ‘李四’, age= null}
  3. Student{name= ‘张三’, age= 1}
  4. Student{name= ‘王小二’, age= 10}
  5. Student{name= ‘赵六’, age= 40}
  6. Student{name= ‘狗子’, age= 99}

降序排序:


 
 
  1. //降序排序
  2. Student studentWang = new Student( “王小二”, 10);
  3. Student studentZhang = new Student( “张三”, 1);
  4. Student studentGou = new Student( “狗子”, 99);
  5. Student studentZhao = new Student( “赵六”, 40);
  6. Student studentLi = new Student( “李四”, null);
  7. List<Student> students = new ArrayList<Student>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
  8. Collections.sort(students, new Comparator<Student>() {
  9. public int compare(Student o1, Student o2) {
  10. if( null == o1.getAge()) {
  11. return 1;
  12. }
  13. if( null == o2.getAge()) {
  14. return - 1;
  15. }
  16. return o2.getAge().compareTo(o1.getAge());
  17. }
  18. });
  19. System.out.println( “自定义对象,降序排序:”);
  20. for(Student student : students) {
  21. System.out.println(student.toString());
  22. }

返回:


 
 
  1. 自定义对象,降序排序:
  2. Student{name= ‘狗子’, age= 99}
  3. Student{name= ‘赵六’, age= 40}
  4. Student{name= ‘王小二’, age= 10}
  5. Student{name= ‘张三’, age= 1}
  6. Student{name= ‘李四’, age= null}


至此对数组、包装类集合、自定义集合排序做了总结,希望对大家有所帮助,如果有错误或问题可以留言在下方,敬请指正。






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值