侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 292 篇文章
  • 累计创建 132 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

java中封装类型和字符串类型List集合排序方法汇总

孔子说JAVA
2022-07-20 / 0 评论 / 0 点赞 / 50 阅读 / 8,347 字 / 正在检测是否收录...

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);
    }
}

image-1658280282909

image-1658277060332

image-1658277347424

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);
}

image-1658279174079

字符串集合测试代码:

@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);
}

image-1658280514052

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]
}
0

评论区