内容简介:在本教程中,我们将首先了解Java 8中的Lambda支持,特别是如何利用它来编写Comparator并对Collection进行排序。首先,让我们定义一个简单的实体类:在Java 8之前,对集合进行排序将涉及为排序中使用的Comparator创建匿名内部类:
简介
在本教程中,我们将首先了解 Java 8中的Lambda支持,特别是如何利用它来编写Comparator并对Collection进行排序。
首先,让我们定义一个简单的实体类:
public class Human { private String name; private int age; }
List的简单排序
在Java 8之前,对集合进行排序将涉及为 排序 中使用的Comparator创建匿名内部类:
new Comparator<Human>() { @Override public int compare(Human h1, Human h2) { return h1.getName().compareTo(h2.getName()); } }
这个比较简单,我看看单元测试的案例:
@Test public void givenPreLambda() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Collections.sort(humans, new Comparator<Human>() { @Override public int compare(Human h1, Human h2) { return h1.getName().compareTo(h2.getName()); } }); Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
Lambda在排序中的使用
随着Lambdas的引入,我们现在可以绕过匿名内部类,并通过简单,功能的语义实现来得到相同的结果:
(final Human h1, final Human h2) -> h1.getName().compareTo(h2.getName());
同样,还是可以用之前的测试用例:
@Test public void test() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); humans.sort( (Human h1, Human h2) -> h1.getName().compareTo(h2.getName())); assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
请注意,我们还使用了添加到Java 8 中的java.util.List的新排序的API,而不是旧的Collections.sort API。
不带类型定义排序
我们可以通过不指定类型定义来进一步简化表达式 - 编译器能够自己推断这些:
(h1, h2) -> h1.getName().compareTo(h2.getName())
测试用例如下:
@Test public void test() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName())); assertThat(humans.get(0), equalTo(new Human("Jack", 12))); }
这个得益于Lambda的方法支持,让我的代码更加简洁。
使用静态方法进行排序
接下来,我们将使用Lambda Expression执行排序,并引用静态方法。
首先,我们将定义方法 compareByNameThenAge
与 Comparator <Human>
对象中的compare方法完全相同返回值:
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(Human::compareByNameThenAge);
看下单元测试
@Test public void test() { List<Human> 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))); }
内部API的进行排序
我们还可以通过使用 Collections
引用和 Comparator.comparing
方法组合进行排序比较。
我们将使用 getName()
来构建Lambda表达式并按名称对List进行排序:
@Test public void test() { List<Human> 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))); }
反向排序
Java 8还引入了一个用于反转比较器的辅助方法,我们可以快速使用它来反转我们的排序:
@Test public void test() { List<Human> humans = Lists.newArrayList( new Human("Sarah", 10), new Human("Jack", 12) ); Comparator<Human> comparator = (h1, h2) -> h1.getName().compareTo(h2.getName()); humans.sort(comparator.reversed()); Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10))); }
多条件排序
比较lambda表达式不一定非常简单,我们也可以编写更复杂的表达式。例如按照name、age进行排序比较。
@Test public void test() { List<Human> 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))); }
多条件组合排序
相同的例子,我们也可以通过Comparator的新组合支持来实现。
从JDK 8开始,我们现在可以将多个比较器组合在一起,以构建更复杂的比较逻辑:
@Test public void test() { List<Human> 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))); }
Stream排序
我们还可以使用Java 8的 Stream sorted()
API 对集合进行排序。
我们可以使用自然排序以及比较器提供的排序对stream进行排序。 为此,我们有 sorted()
,与其对应的有两个API :
- sorted();使用排序对Stream的元素进行排序,元素类必须实现Comparable接口
- sorted(Comparator<? super T> comparator);根据Comparator实例对元素进行排序
让我们看一个如何使用自然排序的sorted()方法的示例:
@Test public final void test() { List<String> letters = Lists.newArrayList("B", "A", "C"); List<String> sortedLetters = letters.stream().sorted().collect(Collectors.toList()); assertThat(sortedLetters.get(0), equalTo("A")); }
现在让我们看看我们如何使用自定义Comparator与sorted():
@Test public final void test() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); Comparator<Human> nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName()); List<Human> sortedHumans = humans.stream().sorted(nameComparator).collect(Collectors.toList()); assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12))); }
如果我们使用 Comparator.comparing()
方法,我们可以进一步简化上面的例子:
@Test public final void test() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); List<Human> sortedHumans = humans.stream() .sorted(Comparator.comparing(Human::getName)) .collect(Collectors.toList()); assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12))); }
Stream反向排序
我们也可以使用Stream.sorted()来反向排序List。
首先,让我们看一个如何将sorted()方法与Comparator.reverseOrder()组合以反向顺序对列表进行排序的示例:
@Test public final void test() { List<String> letters = Lists.newArrayList("B", "A", "C"); List<String> reverseSortedLetters = letters.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); assertThat(reverseSortedLetters.get(0), equalTo("C")); }
现在,让我们看看如何使用sorted()方法和自定义Comparator:
@Test public final void test() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); Comparator<Human> reverseNameComparator = (h1, h2) -> h2.getName().compareTo(h1.getName()); List<Human> reverseSortedHumans = humans.stream().sorted(reverseNameComparator) .collect(Collectors.toList()); assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10))); }
最后,让我们使用Comparator.comparing()方法简化上面的示例:
@Test public final void test() { List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); List<Human> reverseSortedHumans = humans.stream() .sorted(Comparator.comparing(Human::getName, Comparator.reverseOrder())) .collect(Collectors.toList()); assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10))); }
总结
使用Java 8 Lambda表达式对List进行排序,效果是非常不错的,也是Lambda的使用场景之一,这一点展示了Lambda的强大的语义功能。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 从零单排Java 8(2) —— Timestamp、String互转
- 从零单排系列之写一个类vue框架(一)
- 从零单排系列之写一个类vue框架(二)
- AWK 的用法
- AWK基础用法
- UniversalImageLoader的用法总结
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Coming of Age in Second Life
Tom Boellstorff / Princeton University Press / 2008-04-21 / USD 29.95
The gap between the virtual and the physical, and its effect on the ideas of personhood and relationships, is the most interesting aspect of Boellstorff's analysis... Boellstorff's portrayal of a virt......一起来看看 《Coming of Age in Second Life》 这本书的介绍吧!