转自: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]);
}
降序排序,对于需要使用数组 的情况,可以创建一个新的数组,然后倒叙访问赋值,例如:
-
//(2)或者创建一个新的数组,倒叙保存到新数组
-
int[] descArray =
new
int[array.length];
-
for (
int i =
0; i < array.length; i++) {
-
descArray[i] = array[array.length - i -
1];
-
}
-
System.out.println(
“新数组降序输出:”);
-
for (
int num : descArray) {
-
System.out.println(num);
-
}
降序排序,可以先将数组转为集合,然后使用Collections.reverse()反转集合,但是对于非引用类型,不可以使用Arrays.asList(),因为int[]会被当作一个类型,而不是数组。
所以可以使用Guava的Ints.asList()方法实现,该转换后的集合,实现了List接口的方法,直接将数组转入内部的数组变量,需要注意它并没有实现数组的操作方法,例如调用add会报错:
转换和排序例如:
-
//(3)或者使用Guava来实现
-
List<Integer> integersList = Ints.asList(array);
-
Collections.reverse(integersList);
//冒泡交换
-
System.out.println(
“Guava降序输出:”);
-
for (
int num : integersList) {
-
System.out.println(num);
-
}
转后的集合类是Guava中的IntArrayAsList,其类UML图如下:
二、集合Sort排序—包装类
本小节主要是对jdk类库中的包装类排序,例如:Integer、String等,这些类都已经重写了Compare方法,都有默认排序规则,例如对于Integer类型会比较其包装的值类型大小,对于String类型会以长度最小字符串为基准,逐一比较相同位置字符的ASCII码大小,如果都相同则比较字符串的长度。
以Integer为例子,升序排序:
-
//Integer集合,正序排序
-
List<Integer> list =
new ArrayList<Integer>(Arrays.asList(
10,
3,
6,
1,
4,
5,
9));
-
Collections.sort(list);
-
System.out.println(
“集合正序排序:”);
-
for (Integer num : list) {
-
System.out.println(num);
-
}
返回:
-
集合正序排序:
-
1
-
3
-
4
-
5
-
6
-
9
-
10
降序排序:
-
//倒叙排序
-
Comparator<Integer> reverseComparator = Collections.reverseOrder();
-
Collections.sort(list, reverseComparator);
-
System.out.println(
“集合倒叙排序:”);
-
for (Integer num : list) {
-
System.out.println(num);
-
}
返回:
-
集合倒叙排序:
-
10
-
9
-
6
-
5
-
4
-
3
-
1
三、集合Sort排序—自定义对象
除了两节所描述的情况,我们还会遇到对于自定义类排序的情况,例如我们现在有一个学生对象,想要根据年龄对其进行排序,学生类Student如下:
-
public
class Student {
-
-
private String name;
-
-
private Integer age;
-
-
public Student(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;
-
}
-
-
/**
-
* 为了更好显示数据,我们重写toString()方法.
-
* @return 显示变量的字符串
-
*/
-
@Override
-
public String toString() {
-
return
“Student{” +
-
“name=’” + name +
‘’’ +
-
“, age=” + age +
-
‘}’;
-
}
-
}
(1) 第一种方式,是实现Comparable接口,重写接口方法。
该CompareTo()方法,如果指定的数与参数相等返回0;如果指定的数小于参数返回 -1;如果指定的数大于参数返回 1。
对于排序来讲,你可以认为当返回1时,指定的数和参数会进行交换,而非1时则不变,指定数可以当作原本的数组中靠前的数,而参数可以当作靠后的数,又因为只有靠前数大于靠后数时才返回1,所以大的会被放到后面,此时升序排序(方便记忆)。以此类推,倒序情况则相反。
升序排序,比Student类增加了Comparable接口,并实现升序排序:
-
public
class StudentAsc implements Comparable<StudentAsc> {
-
private String name;
-
-
private Integer age;
-
-
public StudentAsc(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;
-
}
-
-
public int compareTo(StudentAsc o) {
-
if(
null ==
this.age) {
-
return -
1;
-
}
-
if(
null == o.getAge()) {
-
return
1;
-
}
-
return
this.age.compareTo(o.getAge());
-
}
-
-
@Override
-
public String toString() {
-
return
“StudentAsc{” +
-
“name=’” + name +
‘’’ +
-
“, age=” + age +
-
‘}’;
-
}
-
-
}
方法调用:
-
//正序排序,年龄为null时为小
-
StudentAsc studentWang =
new StudentAsc(
“王小二”,
10);
-
StudentAsc studentZhang =
new StudentAsc(
“张三”,
1);
-
StudentAsc studentGou =
new StudentAsc(
“狗子”,
99);
-
StudentAsc studentZhao =
new StudentAsc(
“赵六”,
40);
-
StudentAsc studentLi =
new StudentAsc(
“李四”,
null);
-
List<StudentAsc> studentAscs =
new ArrayList<StudentAsc>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
-
Collections.sort(studentAscs);
-
System.out.println(
“自定义对象,升序排序:”);
-
for(StudentAsc studentAsc : studentAscs) {
-
System.out.println(studentAsc.toString());
-
}
返回:
-
自定义对象,升序排序:
-
Student{name=
‘李四’, age=
null}
-
Student{name=
‘张三’, age=
1}
-
Student{name=
‘王小二’, age=
10}
-
Student{name=
‘赵六’, age=
40}
-
Student{name=
‘狗子’, age=
99}
降序排序,比Student类增加了Comparable接口,并实现倒序排序:
-
public
class StudentDesc implements Comparable<StudentDesc> {
-
private String name;
-
-
private Integer age;
-
-
public StudentDesc(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;
-
}
-
-
public int compare(Integer o1, Integer o2) {
-
return o2.compareTo(o1);
-
}
-
-
public int compareTo(StudentDesc o) {
-
if(
null ==
this.age) {
-
return
1;
-
}
-
if(
null == o.getAge()) {
-
return -
1;
-
}
-
return o.age.compareTo(
this.getAge());
-
}
-
-
@Override
-
public String toString() {
-
return
“StudentDesc{” +
-
“name=’” + name +
‘’’ +
-
“, age=” + age +
-
‘}’;
-
}
-
}
方法调用:
-
//降叙排序,年龄为null时为最大
-
StudentDesc studentWang =
new StudentDesc(
“王小二”,
10);
-
StudentDesc studentZhang =
new StudentDesc(
“张三”,
1);
-
StudentDesc studentGou =
new StudentDesc(
“狗子”,
99);
-
StudentDesc studentZhao =
new StudentDesc(
“赵六”,
40);
-
StudentDesc studentLi =
new StudentDesc(
“李四”,
null);
-
List<StudentDesc> studentAscs =
new ArrayList<StudentDesc>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
-
Collections.sort(studentAscs);
-
System.out.println(
“自定义对象,降序排序:”);
-
for(StudentDesc studentAsc : studentAscs) {
-
System.out.println(studentAsc.toString());
-
}
返回:
-
自定义对象,降序排序:
-
Student{name=
‘狗子’, age=
99}
-
Student{name=
‘赵六’, age=
40}
-
Student{name=
‘王小二’, age=
10}
-
Student{name=
‘张三’, age=
1}
-
Student{name=
‘李四’, age=
null}
(2)第二种方式,上面实现Comparable接口的方法并不十分灵活,比如对于一个类,在不同的地方需要使用不同的排序,此时再这样做就会显的十分繁琐。因此我们可以通过Collections.sort(List<T> list, Comparator<? super T> c)方法来实现,例子中,我们使用Student类,例子如下:
升序排序:
-
//升序排序
-
Student studentWang =
new Student(
“王小二”,
10);
-
Student studentZhang =
new Student(
“张三”,
1);
-
Student studentGou =
new Student(
“狗子”,
99);
-
Student studentZhao =
new Student(
“赵六”,
40);
-
Student studentLi =
new Student(
“李四”,
null);
-
List<Student> students =
new ArrayList<Student>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
-
Collections.sort(students,
new Comparator<Student>() {
-
public int compare(Student o1, Student o2) {
-
if(
null == o1.getAge()) {
-
return -
1;
-
}
-
if(
null == o2.getAge()) {
-
return
1;
-
}
-
return o1.getAge().compareTo(o2.getAge());
-
}
-
});
-
System.out.println(
“自定义对象,升序排序:”);
-
for(Student student : students) {
-
System.out.println(student.toString());
-
}
返回:
-
自定义对象,升序排序:
-
Student{name=
‘李四’, age=
null}
-
Student{name=
‘张三’, age=
1}
-
Student{name=
‘王小二’, age=
10}
-
Student{name=
‘赵六’, age=
40}
-
Student{name=
‘狗子’, age=
99}
降序排序:
-
//降序排序
-
Student studentWang =
new Student(
“王小二”,
10);
-
Student studentZhang =
new Student(
“张三”,
1);
-
Student studentGou =
new Student(
“狗子”,
99);
-
Student studentZhao =
new Student(
“赵六”,
40);
-
Student studentLi =
new Student(
“李四”,
null);
-
List<Student> students =
new ArrayList<Student>(Arrays.asList(studentWang, studentZhang, studentGou, studentZhao, studentLi));
-
Collections.sort(students,
new Comparator<Student>() {
-
public int compare(Student o1, Student o2) {
-
if(
null == o1.getAge()) {
-
return
1;
-
}
-
if(
null == o2.getAge()) {
-
return -
1;
-
}
-
return o2.getAge().compareTo(o1.getAge());
-
}
-
});
-
System.out.println(
“自定义对象,降序排序:”);
-
for(Student student : students) {
-
System.out.println(student.toString());
-
}
返回:
-
自定义对象,降序排序:
-
Student{name=
‘狗子’, age=
99}
-
Student{name=
‘赵六’, age=
40}
-
Student{name=
‘王小二’, age=
10}
-
Student{name=
‘张三’, age=
1}
-
Student{name=
‘李四’, age=
null}
至此对数组、包装类集合、自定义集合排序做了总结,希望对大家有所帮助,如果有错误或问题可以留言在下方,敬请指正。