JDK8 按List中元素对象的多字段对List进行排序
利用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进行排序相关推荐
- js给对象添加变量属性 js 更改对象中的属性名 数组对象中每个对象添加一个字段-map用法和forEarch用法
js给对象添加变量属性 & js 更改对象中的属性名 & 数组对象中每个对象添加一个字段-map用法和forEarch用法 1.js给对象添加变量属性 1.js创建一个对象或者在原有对 ...
- java 实体 text字段,如何在Java中修剪对象的某些字段?
小编典典 假设你有三个字段f1,f2,f3中class A 创建一个新class B的字段f1 声明一个方法class A是这样 public B getTrimmedObject() 从A设置B的必 ...
- 无侵入性的在日志中打印对象的关键字段
我们在开发的时候,经常要打印日志,有的时候会在一些代码的关键节点处进行日志输出. 使用logback/log4j等原生的日志框架,在日志输出的时候可能会遇到一个问题,那就是在打印对象的时候要求对象必须 ...
- java 对象多属性排序_java list按照元素对象的指定多个字段属性进行排序
package com.enable.common.utils; import java.lang.reflect.Field; import java.text.NumberFormat; impo ...
- java list按照元素对象的指定多个字段属性进行排序
ListUtils.java---功能类 package com.enable.common.utils; import java.lang.reflect.Field; import java.te ...
- java 对多个元素对象的排序_java list按照元素对象的指定多个字段属性进行排序...
ListUtils.java---功能类 package com.enable.common.utils; import java.lang.reflect.Field; import java.te ...
- java对汉字按照拼音首字母排序_java对象集合中某个属性的汉字进行按拼音进行排序...
在开发中,有些时候我们要对一个集合中的对象的某个属性进行按拼音排序,便于更快的找到汉字,我采用Comparator接口,在实现这个接口里定义排序规则,取得比较对象的汉字编码,并将其转换成字符串,运用S ...
- js中显示一个指定html文档,JS实现选定指定HTML元素对象中指定文本内容功能示例...
本文实例讲述了JS实现选定指定HTML元素对象中指定文本内容功能.分享给大家供大家参考,具体如下: 该功能用处多多,可以灵活运用之!主要函数如下: //选中文本中指定部分 function selec ...
- python内置函数可以返回列表元组_Python内置函数()可以返回列表、元组、字典、集合、字符串以及range对象中元素个数....
Python内置函数()可以返回列表.元组.字典.集合.字符串以及range对象中元素个数. 青岛远洋运输有限公司冷聚吉船长被评为全国十佳海员.()A:错B:对 有源逆变是将直流电逆变成其它频率的交流 ...
最新文章
- nagios 监控NFS
- java爱暮色森林7.0js_我的世界手机版暮色森林js
- c 链表之 快慢指针 查找循环节点(转)
- createTemporaryView is deprecated
- 12c集群日志位置_大数据系列教程006-开启日志聚合功能
- ruby 批量下载王者荣耀皮肤
- Mysql err 1055
- GeoDa 空间自相关操作步骤
- python混合线性模型_Python Statsmodels Mixedlm(混合线性模型)随机效应
- python新手快速入门教程-10 分钟快速入门 Python3的教程
- javaScript中内置对象Date基本操作入门
- Pascal trangle leetcode
- nosql包括的数据库
- 企业即时通讯软件,网络通讯协议和机制怎么选?
- Keep悦动圈竞品分析报告(1)
- 九、用场效应管设计与门
- [BZOJ2548][Ctsc2002]灭鼠行动(大模拟)
- android手机控制电视,[转载]android万能遥控器之二--用手机遥控电视
- 《区块链技术与应用》北大肖臻老师——课程笔记【1-3】
- vr计算机语言,虚拟现实语言