在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),也可以排序;