java开发中,有很多对集合List排序的应用场景,集合中可以是一个基本类型的封装类型,也可以是一个复杂的自定义类的对象。对于有多个属性的对象,有可能依据某个属性来排序,也有可能依据多个属性综合排序,本文主要讲解封装类型和字符串类型集合的排序,对于复杂对象集合的排序将在下一篇文章中讲解。本文所有用例均经过验证,方便学习和速查,可以直接使用。
- 引用类型集合排序参考:java中引用类型对象List集合排序方法汇总
封装类型和字符串类型集合的排序,即 List<E>
集合中存储的 E 类型为java基本类型的封装类型是字符串类型,如Integer、Float、Character、String等,均可以使用如下方式进行排序。
1、使用java.util.Collections工具类
使用java.util.Collections工具类对封装类型的集合进行排序,使用方式相同,下面以Integer、Character、Boolean类型的集合为例说明。
- Collections.sort(java对象),该java对象必须实现Comparable类;封装类型默认都实现了Comparable类,重写了compareTo方法。
- 注意:使用此方式,集合中不能包含null。
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 集合排序
*/
public class ListSort {
@Test
public void integerListSort(){
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(5);
list.add(1);
// list.add(null); // 放开注释后,运行时报空指针异常
// 以下方式同样适用于字符串类型的集合
// List<String> list = Arrays.asList("eee", "ddd", "aaa", "ccc", "bbb");
// Collections工具类,升序排列
Collections.sort(list);
System.out.println(list);
// Collections工具类,降序排列
Collections.reverse(list);
System.out.println(list);
// Collections工具类,自然排序为升序排列
Collections.sort(list, Comparator.naturalOrder());
System.out.println(list);
// Collections工具类,扭转自然排序为降序排列
Collections.sort(list, Comparator.reverseOrder());
System.out.println(list);
}
@Test
public void charListSort(){
List<Character> list = new ArrayList<>();
list.add('a');
list.add('d');
list.add('b');
list.add('m');
// Collections工具类,升序排列
Collections.sort(list);
System.out.println(list);
// Collections工具类,降序排列
Collections.reverse(list);
System.out.println(list);
}
@Test
public void boolListSort(){
List<Boolean> list = new ArrayList<>();
list.add(true);
list.add(false);
list.add(false);
list.add(true);
// Collections工具类,升序排列
Collections.sort(list);
System.out.println(list);
// Collections工具类,降序排列
Collections.reverse(list);
System.out.println(list);
}
}
2、List对象的sort方法
先看一下List对象的sort方法源码,可以看到参数为Comparator对象。
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
对于自然排序,一个类需要实现Comparable并定义compareTo方法。一个对象的集合根据compareTo方法以自然排序进行排序。像Integer、String和Date这样的Java类实现了Comparable接口并覆盖了其compareTo方法,它们以词表顺序(lexicographic-order)进行排序。为了扭转自然排序,我们可以使用Comparator.reverseOrder方法。
Integer集合排序示例:
- 本例中的 Integer::compareTo 为方法引用,它是对List集合中Integer对象的实例方法compareTo的引用,有关方法引用可参考:java方法引用详解
@Test
public void listSort(){
List<Integer> list = Arrays.asList(12, 10, 15, 8, 11);
// 升序
list.sort(Integer::compareTo);
System.out.println(list);
// 以下方式同样适用于字符串类型的集合
// List<String> list = Arrays.asList("eee", "ddd", "aaa", "ccc", "bbb");
// 降序,为了扭转自然排序,我们可以使用Comparator.reverseOrder方法。
list.sort(Comparator.reverseOrder());
System.out.println(list);
// 升序
list.sort(Comparator.naturalOrder());
System.out.println(list);
}
这里也可以使用 Comparator自定义排序,效果一样,只是不够简洁。
整形集合测试代码:
@Test
public void listComparatorSort() {
List<Integer> list = Arrays.asList(12, 10, 15, 8, 11);
// 升序排列
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(list);
// 降序排列
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(list);
}
字符串集合测试代码:
@Test
public void listComparatorSort() {
// 字符串类型集合排序
List<String> list2 = Arrays.asList("eee", "ddd", "aaa", "ccc", "bbb");
// 升序排列
list2.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
System.out.println(list2);
// 降序排列
list2.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
System.out.println(list2);
}
3、Stream结合Lambda方法排序
使用java8新特性,Stream结合Lambda表达式对集合进行排序。
- 有关Lambda可参考:Lambda详解
- 有关Stream可参考:java8新特性Stream流操作详解及实战
- 值得注意的是sorted只是创建一个流对象排序的视图,而不会改变原集合中元素的顺序。也就是说使用sorted方法原有集合的顺序实际上是没有发生变化的。
整形集合测试代码:
@Test
public void streamLambdaSort(){
List<Integer> list = Arrays.asList(12, 10, 15, 8, 11);
// 使用Lambda表达式对2个对象进行比较,并输出排序结果,升序
list.stream().sorted((a,b)->a.compareTo(b)).forEach(System.out::println);
// 此处的list还是原始未排序集合
System.out.println(list);
// 使用Lambda表达式对2个对象进行比较,并输出排序结果,降序
list.stream().sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);
// 此处的list还是原始未排序集合
System.out.println(list);
}
字符串集合测试代码:
@Test
public void streamLambdaSort(){
// 字符串类型集合排序
List<String> list2 = Arrays.asList("eee", "ddd", "aaa", "ccc", "bbb");
// 使用Lambda表达式对2个对象进行比较,并输出排序结果,升序
list2.stream().sorted((a, b) -> a.compareTo(b)).forEach(System.out::println);
// 使用Lambda表达式对2个对象进行比较,并输出排序结果,降序
list2.stream().sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);
}
4、Stream结合Comparator方法排序
naturalOrder是比较器功能接口的静态方法。Java 8中引入的Comparator.naturalOrder方法返回一个比较器,该比较器以自然顺序比较可比较对象。为了扭转自然排序,我们可以使用Comparator.reverseOrder方法。
- 值得注意的是sorted只是创建一个流对象排序的视图,而不会改变原集合中元素的顺序。也就是说使用sorted方法原有集合的顺序实际上是没有发生变化的。
整形集合测试代码:
@Test
public void streamComparatorSort(){
List<Integer> list = Arrays.asList(12, 10, 15, 8, 11);
// java.util.Comparator.naturalOrder() 自然排序,并输出排序结果,升序
list.stream().sorted(Comparator.naturalOrder()).forEach(System.out::println);
// 此处的list还是原始未排序集合
System.out.println(list);
// java.util.Comparator.reverseOrder() 扭转自然排序,并输出排序结果,降序
list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
// 此处的list还是原始未排序集合
System.out.println(list);
}
字符串集合测试代码:
@Test
public void streamComparatorSort(){
// 字符串类型集合排序
List<String> list2 = Arrays.asList("eee", "ddd", "aaa", "ccc", "bbb");
// 使用Lambda表达式对2个对象进行比较,并输出排序结果,升序
list2.stream().sorted((a, b) -> a.compareTo(b)).forEach(System.out::println);
// 使用Lambda表达式对2个对象进行比较,并输出排序结果,降序
list2.stream().sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);
}
5、Arrays.sort方法排序
将List转化为Array,再用Arrays.sort方法排序。
整形集合测试代码:
@Test
public void arraysSort() {
List<Integer> list = Arrays.asList(12, 10, 15, 8, 11);
Integer[] array = (Integer[])list.toArray();
// 升序
System.out.print("升序: ");
Arrays.sort(array, Comparator.naturalOrder());
for(Integer s: array) {
System.out.print(s+", ");
}
System.out.println("");
System.out.print("降序: ");
// 降序
Arrays.sort(array, Comparator.reverseOrder());
for(Integer s: array) {
System.out.print(s+", ");
}
}
字符串集合测试代码:
@Test
public void arraysSort() {
// 字符串类型集合排序
List<String> list2 = Arrays.asList("eee", "ddd", "aaa", "ccc", "bbb");
String[] array2 = (String[])list2.toArray();
Arrays.sort(array2, Comparator.naturalOrder());
System.out.print("String升序: ");
for(String s: array2) {
System.out.print(s+", ");
}
System.out.println("");
System.out.print("String降序: ");
// 降序
Arrays.sort(array2, Comparator.reverseOrder());
for(String s: array2) {
System.out.print(s+", ");
}
}
6、集合中存在null的排序方式
这里用到google的guava包,需要先引入以下pom。
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
<scope>compile</scope>
</dependency>
</dependencies>
整形集合测试代码:
@Test
public void hasNullsort() {
// org.assertj.core.util.Lists;
List<Integer> list = Lists.newArrayList();
list.add(1);
list.add(3);
list.add(2);
list.add(null);
// com.google.common.collect.Ordering; 需要引入
Ordering<Comparable> natural = Ordering.natural();
Collections.sort(list, natural.nullsLast());
System.out.println("list = " + list);
// 输出list = [1, 2, 3, null]
Collections.sort(list, natural.nullsFirst());
System.out.println("list = " + list);
// 输出list = [null, 1, 2, 3]
list.removeIf(e -> Objects.isNull(e));
Collections.sort(list);
System.out.println("list = " + list);
// 输出list = [1, 2, 3]
}
字符串集合测试代码:
@Test
public void hasNullsort() {
// 字符串类型集合排序
List<String> list2 = new ArrayList<>();
list2.add("aaa");
list2.add("ddd");
list2.add("bbb");
list2.add("ccc");
list2.add(null);
Ordering<Comparable> natural1 = Ordering.natural();
Collections.sort(list2, natural1.nullsLast());
System.out.println("list2 = " + list2);
// 输出list2 = [aaa, bbb, ccc, ddd, null]
Collections.sort(list2, natural1.nullsFirst());
System.out.println("list2 = " + list2);
// 输出list2 = [null, aaa, bbb, ccc, ddd]
list2.removeIf(e -> Objects.isNull(e));
Collections.sort(list2);
System.out.println("list2 = " + list2);
// 输出list2 = [aaa, bbb, ccc, ddd]
}
评论区