Thales的博客站
切换导航
导航
博客首页
关于博主
CV
工具
博客信息
使用Lambda快速构建Comparator
标签
:
java
作者:Thales 尊重博主原创文章,转载请注明文章出于此处。
## 1.概述 在算法笔试过程中,我们经常会遇到一些排序(有时候并不会要求我们编写排序本身的代码,而是要求我们对数据做一些简单的处理),Collections工具类和List提供了排序算法,大师要求我们为排序方法传递一个Comparator,我们经常使用匿名类来实现这个Comparator,但是仍显繁冗。本文就此目的总结了一些使用Lambda实现Comparator的方法。 在本文,我们将首先介绍Java 8中的Lambda支持 - 特别是如何利用它来编写Comparator并对Collection进行排序。 首先,让我们定义一个简单的实体类: ```java public class Human { private String name; private int age; public Human() { super(); } public Human(String name, int age) { super(); this.name = name; this.age = age; } // standard getters/setters, equals and hashcode } ``` ## 2.没有Lambdas的基本排序 在Java 8之前,对集合进行排序一般要为sort使用的Comparator创建匿名内部类: ```java new Comparator
() { @Override public int compare(Human h1, Human h2) { return h1.getName().compareTo(h2.getName()); } } ``` 这只会被用来排序Person实体的name: ## 3.有Lambda支持的基本排序 随着Lambdas的引入,我们现在可以绕过匿名内部类,并通过简单,功能性的语义实现相同的结果: ```java (final Human h1, final Human h2) -> h1.getName().compareTo(h2.getName()); ``` 在这里我们还使用了在Java 8中添加到java.util.List的新的sort API,而不是旧的Collections.sort API ## 4.没有类型定义的基本排序 我们可以通过不指定类型定义来进一步简化表达式——编译器能够自己推断这些: ```java (h1, h2) -> h1.getName().compareTo(h2.getName()) ``` ## 5.使用引用静态方法排序 接下来,我们将使用Lambda Expression执行排序,并引用静态方法。 首先,我们将定义方法compareByNameThenAge - 与Comparator
对象中的compare方法完全相同的签名: ```java public static int compareByNameThenAge(Human lhs, Human rhs) { if (lhs.name.equals(rhs.name)) { return lhs.age - rhs.age; } else { return lhs.name.compareTo(rhs.name); } } ``` 现在,我们将使用此引用调用humans.sort方法: ```java humans.sort(Human::compareByNameThenAge); ``` 最终结果是使用静态方法作为比较器对集合进行排序: ```java @Test public void givenMethodDefinition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List
humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); humans.sort(Human::compareByNameThenAge); Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12))); } ``` ## 6.使用提取的Comparator进行排序 我们还可以通过使用实例方法引用和Comparator.comparing方法来避免定义比较逻辑本身- 该方法基于该函数提取和创建Comparable。 我们将使用getter getName()来构建Lambda表达式并按名称对列表进行排序: ```java @Test public void givenInstanceMethod_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List
humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Collections.sort( humans, Comparator.comparing(Human::getName)); assertThat(humans.get(0), equalTo(new Human("Jack", 12))); } ``` ## 7.反向排序 JDK 8还引入了一个用于反转比Comparator的辅助方法- 我们可以快速使用它来反转我们的排序: ```java @Test public void whenSortingEntitiesByNameReversed_thenCorrectlySorted() { List
humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Comparator
comparator = (h1, h2) -> h1.getName().compareTo(h2.getName()); humans.sort(comparator.reversed()); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); } ``` ## 8.按多个条件排序 比较lambda表达式不一定非常简单,我们也可以编写更复杂的表达式。例如,首先按名称排序实体,然后按年龄排序: ```java @Test public void whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List
humans = Lists.newArrayList( new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12) ); humans.sort((lhs, rhs) -> { if (lhs.getName().equals(rhs.getName())) { return lhs.getAge() - rhs.getAge(); } else { return lhs.getName().compareTo(rhs.getName()); } }); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); } ``` ## 9.按多个条件排序——组合 相同的比较逻辑,首先按名称排序,然后按年龄排序 也可以通过Comparator的新组合支持来实现。 从JDK 8开始,我们现在可以将多个比较器链接在一起,以构建更复杂的比较逻辑: ```java @Test public void givenComposition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() { List
humans = Lists.newArrayList( new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12) ); humans.sort( Comparator.comparing(Human::getName).thenComparing(Human::getAge) ); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); } ```
发布于:『2018-09-05 15:21』
博客类别:
java
阅读(2665) 评论(0)
上一篇:
netty 简介
下一篇:
Java中的继承和组合(is-a vs has-a关系)
用户评论
暂无评论
发表评论
验证码:
发表评论
文章分类
java(10)
Spring(0)
其它(1)
文章存档
2018年10月(1)
2018年09月(8)
2018年07月(2)
友情链接
分享到
暂无评论