利用Java8按照元素对象的多字段对List进行排序

实例对象

public class WarningRule implements Serializable {private String hour;private String content;//类型排序字段private Integer order;public WarningRule() {}public WarningRule(String hour, Integer order,String content ) {this.hour = hour;this.content = content;this.order = order;}public String getHour() {return hour;}public void setHour(String hour) {this.hour = hour;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public Integer getOrder() {return order;}public void setOrder(Integer order) {this.order = order;}
}

按照hour和order对List<WarningRule>进行排序,hour相同的时候按照order进行排序

Comparator<WarningRule> bya = Comparator.comparing(WarningRule::getHour).reversed();//按照a升序
Comparator<WarningRule> byb = Comparator.comparing(WarningRule::getOrder);//按照b升序
Collections.sort(warningRules,bya.thenComparing(byb));

看一下其中Comparator的源码:

@FunctionalInterface
public interface Comparator<T> {int compare(T o1, T o2);...default Comparator<T> thenComparing(Comparator<? super T> other) {Objects.requireNonNull(other);return (Comparator<T> & Serializable) (c1, c2) -> {int res = compare(c1, c2);return (res != 0) ? res : other.compare(c1, c2);};}...public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor){Objects.requireNonNull(keyExtractor);return (Comparator<T> & Serializable)(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));}...
}

上面只列出了部分代码,可以看出其是一个函数式接口

Comparator<WarningRule> bya = Comparator.comparing(WarningRule::getHour);
我们看一下comparing方法

从上面的源码可以看出这个函数是默认函数,接收的参数是一个函数式接口,即可以传入像例子中的(WarningRule::getHour)类型的方法引用。apply方法接受一个参数返回一个值,即像例子中接收一个WarningRule对象返回其中的hour属性值

返回一个Comparator类型的函数

其返回的Comparator类型的对象利用了lambda表达式,因为Comparator是一个函数式接口,要实现其

int compare(T o1, T o2);

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor){Objects.requireNonNull(keyExtractor);return (Comparator<T> & Serializable)(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));}

return的是Comparator类型的对象,(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));相当于是Comparator接口的匿名内部类,lambda表达式接收两个参数返回一个int类型的数,就是实现了int compare(T o1, T o2);方法。

而Collections.sort(warningRules,bya.thenComparing(byb));

排序则利用了Comparator的compare方法,看jdk的TimSort类的源码

private static <T> void binarySort(T[] a, int lo, int hi, int start,Comparator<? super T> c) {assert lo <= start && start <= hi;if (start == lo)start++;for ( ; start < hi; start++) {T pivot = a[start];// Set left (and right) to the index where a[start] (pivot) belongsint left = lo;int right = start;assert left <= right;/** Invariants:*   pivot >= all in [lo, left).*   pivot <  all in [right, start).*/while (left < right) {int mid = (left + right) >>> 1;//利用Comparator的compare方法if (c.compare(pivot, a[mid]) < 0)right = mid;elseleft = mid + 1;}assert left == right;/** The invariants still hold: pivot >= all in [lo, left) and* pivot < all in [left, start), so pivot belongs at left.  Note* that if there are elements equal to pivot, left points to the* first slot after them -- that's why this sort is stable.* Slide elements over to make room for pivot.*/int n = start - left;  // The number of elements to move// Switch is just an optimization for arraycopy in default caseswitch (n) {case 2:  a[left + 2] = a[left + 1];case 1:  a[left + 1] = a[left];break;default: System.arraycopy(a, left, a, left + 1, n);}a[left] = pivot;}}

可以看出排序利用了我们需要实现的Comparator接口的compare方法。

在我们上面所述的实例中compare方法的参数传入的是两个WarningRule类型的对象,

调用compare方法,而compare方法就是(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)),

其中的keyExtractor就是WarningRule::getHour。

接下来看thenComparing方法:

bya.thenComparing(byb)

default Comparator<T> thenComparing(Comparator<? super T> other) {Objects.requireNonNull(other);return (Comparator<T> & Serializable) (c1, c2) -> {int res = compare(c1, c2);return (res != 0) ? res : other.compare(c1, c2);};}

这个方法接收一个Comparator类型的参数,它先调用自身的compare进行比较,如果返回0说明当前两个对象的这个属性值相等,则调用other的compare 去比较other这个Comparator当时实现compare时传入给compare做参数的对象的属性值

即byb 参数WarningRule的属性值order

如想对对象的一些属性进行降序,例如对hour进行降序,值相同时对order进行升序,可以

 Comparator<WarningRule> bya = Comparator.comparing(WarningRule::getHour).reversed();//按照a降序Comparator<WarningRule> byb = Comparator.comparing(WarningRule::getOrder);//按照b升序

看一下reversed()的源码:

default Comparator<T> reversed() {return Collections.reverseOrder(this);}

继续往下:

public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {if (cmp == null)return reverseOrder();if (cmp instanceof ReverseComparator2)return ((ReverseComparator2<T>)cmp).cmp;return new ReverseComparator2<>(cmp);}

继续:

ReverseComparator2(Comparator<T> cmp) {assert cmp != null;this.cmp = cmp;}public int compare(T t1, T t2) {return cmp.compare(t2, t1);}

可以看到将Comparator转化为ReverseCpmparator2,是Collections的内部类。

private static class ReverseComparator2<T> implements Comparator<T>,Serializable{private static final long serialVersionUID = 4374092139857L;/*** The comparator specified in the static factory.  This will never* be null, as the static factory returns a ReverseComparator* instance if its argument is null.** @serial*/final Comparator<T> cmp;ReverseComparator2(Comparator<T> cmp) {assert cmp != null;this.cmp = cmp;}public int compare(T t1, T t2) {return cmp.compare(t2, t1);}public boolean equals(Object o) {return (o == this) ||(o instanceof ReverseComparator2 &&cmp.equals(((ReverseComparator2)o).cmp));}public int hashCode() {return cmp.hashCode() ^ Integer.MIN_VALUE;}@Overridepublic Comparator<T> reversed() {return cmp;}}

看其中的compare方法:

 public int compare(T t1, T t2) {return cmp.compare(t2, t1);}

比t1和t2的值进行交换,以达到逆序效果。

JDK8 按List中元素对象的多字段对List进行排序相关推荐

  1. js给对象添加变量属性 js 更改对象中的属性名 数组对象中每个对象添加一个字段-map用法和forEarch用法

    js给对象添加变量属性 & js 更改对象中的属性名 & 数组对象中每个对象添加一个字段-map用法和forEarch用法 1.js给对象添加变量属性 1.js创建一个对象或者在原有对 ...

  2. java 实体 text字段,如何在Java中修剪对象的某些字段?

    小编典典 假设你有三个字段f1,f2,f3中class A 创建一个新class B的字段f1 声明一个方法class A是这样 public B getTrimmedObject() 从A设置B的必 ...

  3. 无侵入性的在日志中打印对象的关键字段

    我们在开发的时候,经常要打印日志,有的时候会在一些代码的关键节点处进行日志输出. 使用logback/log4j等原生的日志框架,在日志输出的时候可能会遇到一个问题,那就是在打印对象的时候要求对象必须 ...

  4. java 对象多属性排序_java list按照元素对象的指定多个字段属性进行排序

    package com.enable.common.utils; import java.lang.reflect.Field; import java.text.NumberFormat; impo ...

  5. java list按照元素对象的指定多个字段属性进行排序

    ListUtils.java---功能类 package com.enable.common.utils; import java.lang.reflect.Field; import java.te ...

  6. java 对多个元素对象的排序_java list按照元素对象的指定多个字段属性进行排序...

    ListUtils.java---功能类 package com.enable.common.utils; import java.lang.reflect.Field; import java.te ...

  7. java对汉字按照拼音首字母排序_java对象集合中某个属性的汉字进行按拼音进行排序...

    在开发中,有些时候我们要对一个集合中的对象的某个属性进行按拼音排序,便于更快的找到汉字,我采用Comparator接口,在实现这个接口里定义排序规则,取得比较对象的汉字编码,并将其转换成字符串,运用S ...

  8. js中显示一个指定html文档,JS实现选定指定HTML元素对象中指定文本内容功能示例...

    本文实例讲述了JS实现选定指定HTML元素对象中指定文本内容功能.分享给大家供大家参考,具体如下: 该功能用处多多,可以灵活运用之!主要函数如下: //选中文本中指定部分 function selec ...

  9. python内置函数可以返回列表元组_Python内置函数()可以返回列表、元组、字典、集合、字符串以及range对象中元素个数....

    Python内置函数()可以返回列表.元组.字典.集合.字符串以及range对象中元素个数. 青岛远洋运输有限公司冷聚吉船长被评为全国十佳海员.()A:错B:对 有源逆变是将直流电逆变成其它频率的交流 ...

最新文章

  1. nagios 监控NFS
  2. java爱暮色森林7.0js_我的世界手机版暮色森林js
  3. c 链表之 快慢指针 查找循环节点(转)
  4. createTemporaryView is deprecated
  5. 12c集群日志位置_大数据系列教程006-开启日志聚合功能
  6. ruby 批量下载王者荣耀皮肤
  7. Mysql err 1055
  8. GeoDa 空间自相关操作步骤
  9. python混合线性模型_Python Statsmodels Mixedlm(混合线性模型)随机效应
  10. python新手快速入门教程-10 分钟快速入门 Python3的教程
  11. javaScript中内置对象Date基本操作入门
  12. Pascal trangle leetcode
  13. nosql包括的数据库
  14. 企业即时通讯软件,网络通讯协议和机制怎么选?
  15. Keep悦动圈竞品分析报告(1)
  16. 九、用场效应管设计与门
  17. [BZOJ2548][Ctsc2002]灭鼠行动(大模拟)
  18. android手机控制电视,[转载]android万能遥控器之二--用手机遥控电视
  19. 《区块链技术与应用》北大肖臻老师——课程笔记【1-3】
  20. vr计算机语言,虚拟现实语言

热门文章

  1. 统计学—假设检验之Z检验,T检验
  2. 概率统计Python计算:单个正态总体均值双侧假设的Z检验
  3. 【论文翻译】Cross-Calibration of Push-Broom 2D LIDARs and Cameras In Natural Scenes论文学习笔记
  4. 行业数据和报告到底应该如何去找?
  5. 机器学习的激励函数的故事
  6. 小白如何解决笔记本卡 磁盘占用100
  7. [附源码]Java计算机毕业设计SSM花田音乐网站
  8. 练习:求列表(整数列表)平衡点
  9. 【Music】音乐切换封面没有变化
  10. Axure中继器结构与原理详解