Java Stream流sorted的多字段排序问题(使用reversed()避坑)

在Java中,我们Stream时,会使用到sorted() 方法 进行排序处理
/**
     * Returns a stream consisting of the elements of this stream, sorted
     * according to the provided {@code Comparator}.
     *
     * <p>For ordered streams, the sort is stable.  For unordered streams, no
     * stability guarantees are made.
     *
     * <p>This is a <a href="package-summary.html#StreamOps">stateful
     * intermediate operation</a>.
     *
     * @param comparator a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                   <a href="package-summary.html#Statelessness">stateless</a>
     *                   {@code Comparator} to be used to compare stream elements
     * @return the new stream
     */
    Stream<T> sorted(Comparator<? super T> comparator);

sorted()需要传入一个Comparator比较器,常用的就是Comparator.comparing(), 当然还有Comparator.comparingInt()、Comparator.comparingLong()、Comparator.comparingDouble() 等常用类型值比较器;

在进行单字段排序时,默认就是使用指定字段值升序进行排序, 如果加上reversed()则是进行降序排序。
但是,我们在日常开发中难免会遇到使用元素的多个属性值进行排序,对于后端开发人员来说,因为习惯 SQL 的排序方式后
-- COLUMN_SORT1_NAME 按降序,(COLUMN_SORT1_NAME相同时) COLUMN_SORT2_NAME 按升序 
SELECT * FROM TABLE_NAME WHERE COLUMN_NAME = VALUE ORDER BY COLUMN_SORT1_NAME DESC, COLUMN_SORT2_NAME ASC
会误认为sorted()中的多字段排序相同。
下面我们用示例来说明

定义一个类:

@Data
public class TestComparatorComparingMultiple{
    private String sort1; //排序字段1
    private String sort2; //排序字段2

    public TestComparatorComparingMultiple(String sort1, String sort2){
        this.sort1 = sort1;
        this.sort2 = sort2;
    }
}

初始化一个集合:

public static void main(String[] args) {

        List<TestComparatorComparingMultiple> bs = new ArrayList<>();
        bs.add(new TestComparatorComparingMultiple("555","222"));
        bs.add(new TestComparatorComparingMultiple("222","555"));
        bs.add(new TestComparatorComparingMultiple("111","666"));
        bs.add(new TestComparatorComparingMultiple("444","333"));
        bs.add(new TestComparatorComparingMultiple("222","444"));
        bs.add(new TestComparatorComparingMultiple("666","333"));
        bs.add(new TestComparatorComparingMultiple("333","333"));
}

初始顺序: 在这里插入图片描述
通过不同场景来分析排序:

//场景一
List<TestComparatorComparingMultiple> sortResult1 = bs.stream()
                .sorted(Comparator.comparing(TestComparatorComparingMultiple::getSort1)
                        .thenComparing(TestComparatorComparingMultiple::getSort2)
                )
                .collect(Collectors.toList());
 //场景二            
List<TestComparatorComparingMultiple> sortResult2 = bs.stream()
        .sorted(Comparator.comparing(TestComparatorComparingMultiple::getSort1)
                .thenComparing(TestComparatorComparingMultiple::getSort2).reversed()
        )
        .collect(Collectors.toList());
//场景三
List<TestComparatorComparingMultiple> sortResult3 = bs.stream()
        .sorted(Comparator.comparing(TestComparatorComparingMultiple::getSort1).reversed()
                .thenComparing(TestComparatorComparingMultiple::getSort2)
        )
        .collect(Collectors.toList());
//场景四
List<TestComparatorComparingMultiple> sortResult4 = bs.stream()
        .sorted(Comparator.comparing(TestComparatorComparingMultiple::getSort1).reversed()
                .thenComparing(TestComparatorComparingMultiple::getSort2).reversed()
        )
        .collect(Collectors.toList());

运行以上得到结果:
场景一:
在这里插入图片描述
结果: sort1 升序 、 sort2 升序
没有reversed()时,第一个字段升序 ,第一个字段相同时 第二个字段按升序

场景二:
在这里插入图片描述
结果: sort1 降序 、 sort2 降序
reversed()在最后一个字段时,第一个字段降序 ,第一个字段相同时 第二个字段按降序 (相当于就是场景一取反)

场景三:
在这里插入图片描述
结果: sort1 降序 、 sort2 升序
reversed()在一个字段时 第一个字段降序 ,第一个字段相同时,第二个字段按升序

场景四:
在这里插入图片描述
结果: sort1 升序、 sort2 降序
reversed()两个字段时,第一个字段升序 , 第一个字段相同时 第二个字段按降序 (相当于就是场景三取反)

综上结果得到:
当reversed()在最后一个字段时,就会将之前的所有排序规则取反(区别SQL中的指定字段排序)。

通过reversed()方法的源码,去理解该逻辑。

 /**
	 * 返回一个该顺序相反比较器
     * Returns a comparator that imposes the reverse ordering of this
     * comparator.
     *
     * @return a comparator that imposes the reverse ordering of this
     *         comparator.
     * @since 1.8
     */
    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

避坑,避坑…
当然 Collections.sort() , java.util.List 下的 sort(Comparator<? super E> c),也可以排序;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值