Array、List、Stream排序详解

乔欣 Java经验 发布时间:2023-03-09 21:14:09 阅读数:11716 1
在日常开发中,排序是我们经常遇到的问题,那么java代码如何排序呢?
下文笔者先讲述两个接口,那就是Comparable接口,Comparator接口

Comparable接口源码

package java.lang;

public interface Comparable<T> {  
    public int compareTo(T o);
}
此接口会返回一个整数
返回正数
   代表当前对象大于被比较的对象;
返回0
   代表当前对象等于于被比较的对象;
返回负数 
   代表当前对象小于被比较的对象。

注意事项:
   1.当实现此接口后
     可使用Arrays.sort()和Collections.sort()进行排序
   2.常见的类String,Integer,Double,Date等都实现了Comparable接口
例:Date类中Comparable接口的实现源码
public int compareTo(Date anotherDate) {
    long thisTime = getMillisOf(this);
    long anotherTime = getMillisOf(anotherDate);
    return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
}

Comparator接口源码

package java.util;

@FunctionalInterface
public interface Comparator<T> {   
    int compare(T o1, T o2);    
}
它是一个函数式接口
  它的compare方法有两个参数
   代表进行比较的两个对象
   这个接口代表了可以作为某种对象比较的一种法则
   或叫一种策略 
它的返回值正负代表意义与Comparable接口的方法一样。

Comparator有三种实现方式

实现类
匿名类
Lambda表达式

数组排序Arrays

Arrays的sort方法
可对实现Comparable接口
进行排序
同时还可指定排序的范围
//Arrays.sort对String进行排序
String[] strings = {"de", "dc", "aA", "As", "k", "b"};
Arrays.sort(strings);
assertTrue(Arrays.equals(strings,
        new String[]{"As", "aA", "b", "dc", "de", "k"}));
//Arrays.sort指定范围排序
strings = new String[]{"z", "a", "d", "b"};
Arrays.sort(strings, 0, 3);
assertTrue(Arrays.equals(strings,
        new String[]{"a", "d", "z", "b"}));
//Arrays.sort对基本类型排序
int[] nums = {3, 1, 20, 2, 38, 2, 94};
Arrays.sort(nums);
assertTrue(Arrays.equals(nums,
        new int[]{1, 2, 2, 3, 20, 38, 94}));
//Arrays.parallelSort多线程排序
nums = new int[]{3, 1, 20, 2, 38, 2, 94};
Arrays.parallelSort(nums);
assertTrue(Arrays.equals(nums,
        new int[]{1, 2, 2, 3, 20, 38, 94}));

实现类的比较

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Person {
    private String name;
    private int age;
}

排序
//Arrays.sort提供Comparator进行排序
Person[] persons = new Person[]{
        new Person("Larry", 18),
        new Person("David", 30),
        new Person("James", 20),
        new Person("Harry", 18)};

Arrays.sort(persons, Comparator.comparingInt(Person::getAge));

assertTrue(Arrays.equals(persons, new Person[]{
        new Person("Larry", 18),
        new Person("Harry", 18),
        new Person("James", 20),
        new Person("David", 30)}));

list排序Collections

对实现Comparable的类进行排序
//Collections.sort对于实现Comparable的类进行排序
List<String> names = asList("Larry", "Harry", "James", "David");
Collections.sort(names);
assertEquals(names, asList("David", "Harry", "James", "Larry"));

使用Comparator排序

//Collections.sort提供Comparator进行排序
List<Person> persons2 = asList(
        new Person("Larry", 18),
        new Person("David", 30),
        new Person("James", 20),
        new Person("Harry", 18));
Collections.sort(persons2, Comparator.comparingInt(Person::getAge));
assertEquals(persons2, asList(
        new Person("Larry", 18),
        new Person("Harry", 18),
        new Person("James", 20),
        new Person("David", 30)));

List排序

List接口有sort(Comparator<? super E> c)方法
  可以实现对自身的排序,会影响自身的顺序。
//List.sort排序
names = asList("Larry", "Harry", "James", "David");
names.sort(Comparator.naturalOrder());
assertEquals(names, asList("David", "Harry", "James", "Larry"));

Stream排序

Stream提供sorted()和sorted(Comparator<? super T> comparator)进行排序,会返回一个新的Stream。

//Stream.sorted排序
names = asList("Larry", "Harry", "James", "David");
List<String> result = names.stream()
        .sorted()
        .collect(Collectors.toList());
assertEquals(result, asList("David", "Harry", "James", "Larry"));

//Stream.sorted提供Comparator排序
names = asList("Larry", "Harry", "James", "David");
result = names.stream()
        .sorted(Comparator.naturalOrder())
        .collect(Collectors.toList());
assertEquals(result, asList("David", "Harry", "James", "Larry"));

单字段排序

对类单字段进行排序,使用以下方式即可
Comparator.comparing(类名::属性getter) 

//排序后,反转
Comparator.comparing(类名::属性getter).reversed()
或Comparator.comparing(类名::属性getter, Comparator.reverseOrder())

例
//单字段排序-升序
List<Person> personList = asList(
        new Person("Larry", 18),
        new Person("David", 30),
        new Person("David", 3),
        new Person("James", 20),
        new Person("Harry", 18));
List<Person> personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName))
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("David", 30),
        new Person("David", 3),
        new Person("Harry", 18),
        new Person("James", 20),
        new Person("Larry", 18)));

//单字段排序-倒序1
personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName).reversed())
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("Larry", 18),
        new Person("James", 20),
        new Person("Harry", 18),
        new Person("David", 30),
        new Person("David", 3)));
//单字段排序-倒序2
personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName, Comparator.reverseOrder()))
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("Larry", 18),
        new Person("James", 20),
        new Person("Harry", 18),
        new Person("David", 30),
        new Person("David", 3)));

多字段排序

使用thenComparing进行连接即可

Comparator.comparing(类名::属性一getter).thenComparing(类名::属性二getter)
//多字段排序-1升2升
personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName)
                .thenComparing(Person::getAge))
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("David", 3),
        new Person("David", 30),
        new Person("Harry", 18),
        new Person("James", 20),
        new Person("Larry", 18)));

//多字段排序-1升2倒
personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName)
                .thenComparing(Person::getAge, Comparator.reverseOrder()))
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("David", 30),
        new Person("David", 3),
        new Person("Harry", 18),
        new Person("James", 20),
        new Person("Larry", 18)));

//多字段排序-1倒2升
personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName, Comparator.reverseOrder())
                .thenComparing(Person::getAge))
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("Larry", 18),
        new Person("James", 20),
        new Person("Harry", 18),
        new Person("David", 3),
        new Person("David", 30)));

//多字段排序-1倒2倒
personResult = personList.stream()
        .sorted(Comparator.comparing(Person::getName, Comparator.reverseOrder())
                .thenComparing(Person::getAge, Comparator.reverseOrder()))
        .collect(Collectors.toList());
assertEquals(personResult, asList(
        new Person("Larry", 18),
        new Person("James", 20),
        new Person("Harry", 18),
        new Person("David", 30),
        new Person("David", 3)));
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202303/16783689775984.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者