Java 8 Friday Goodies:Lambda和排序
在Data Geekery ,我們喜歡Java。 而且,由于我們真的很喜歡jOOQ的流暢的API和查詢DSL ,我們對(duì)Java 8將為我們的生態(tài)系統(tǒng)帶來什么感到非常興奮。 我們已經(jīng)寫了一些關(guān)于Java 8好東西的博客 ,現(xiàn)在我們覺得是時(shí)候開始一個(gè)新的博客系列了……
Java 8星期五
每個(gè)星期五,我們都會(huì)向您展示一些不錯(cuò)的教程風(fēng)格的Java 8新功能,這些功能利用了lambda表達(dá)式,擴(kuò)展方法和其他好東西。 您可以在GitHub上找到源代碼 。
Java 8 Goodie:Lambda和排序
排序數(shù)組和集合是Java 8 lambda表達(dá)式的絕佳用例,原因很簡(jiǎn)單,因?yàn)镃omparator自從JDK 1.2引入以來一直一直是@FunctionalInterface 。 現(xiàn)在,我們可以將lambda表達(dá)式形式的Comparators提供給各種sort()方法。
對(duì)于以下示例,我們將使用此簡(jiǎn)單的Person類:
static class Person {final String firstName;final String lastName;Person(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}@Overridepublic String toString() {return "Person{" +"firstName='" + firstName + '\'' +", lastName='" + lastName + '\'' +'}';} }顯然,我們也可以通過使它實(shí)現(xiàn)Comparable來向Person添加自然排序,但讓我們關(guān)注外部Comparators 。 考慮以下Person列表,其名稱是使用一些在線隨機(jī)名稱生成器生成的:
List<Person> people = Arrays.asList(new Person("Jane", "Henderson"),new Person("Michael", "White"),new Person("Henry", "Brighton"),new Person("Hannah", "Plowman"),new Person("William", "Henderson") );我們可能想按姓氏然后按名字對(duì)它們進(jìn)行排序。
用Java 7排序
這樣的Comparator器的一個(gè)“經(jīng)典” Java 7示例是這樣的:
people.sort(new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {int result = o1.lastName.compareTo(o2.lastName);if (result == 0)result = o1.firstName.compareTo(o2.firstName);return result;} }); people.forEach(System.out::println);以上將產(chǎn)生:
Person{firstName='Henry', lastName='Brighton'} Person{firstName='Jane', lastName='Henderson'} Person{firstName='William', lastName='Henderson'} Person{firstName='Hannah', lastName='Plowman'} Person{firstName='Michael', lastName='White'}用Java 8排序
現(xiàn)在,讓我們將以上內(nèi)容翻譯為等效的Java 8代碼:
Comparator<Person> c = (p, o) ->p.lastName.compareTo(o.lastName);c = c.thenComparing((p, o) ->p.firstName.compareTo(o.firstName));people.sort(c); people.forEach(System.out::println);結(jié)果顯然是相同的。 如何閱讀以上內(nèi)容? 首先,我們將lambda表達(dá)式分配給本地Person Comparator變量:
Comparator<Person> c = (p, o) ->p.lastName.compareTo(o.lastName);與Scala,C#或Ceylon不同,后者通過val關(guān)鍵字(或類似關(guān)鍵字) 知道從表達(dá)式到局部變量聲明的類型推斷,而Java從變量(或參數(shù),成員)聲明到要分配的表達(dá)式執(zhí)行類型推斷。
換句話說,類型推斷是從“左到右”而不是從“右到左”執(zhí)行的。 這使得鏈接Comparators有點(diǎn)麻煩,因?yàn)镴ava編譯器在將比較器傳遞給sort()方法之前不能延遲lambda表達(dá)式的類型推斷 。
但是,一旦為變量分配了Comparator ,就可以通過thenComparing()流暢地鏈接其他比較器:
c = c.thenComparing((p, o) ->p.firstName.compareTo(o.firstName));最后,我們將其傳遞給List的新sort()方法,這是直接在List接口上實(shí)現(xiàn)的默認(rèn)方法:
default void sort(Comparator<? super E> c) {Collections.sort(this, c); }上述限制的解決方法
雖然Java的類型推斷“局限性”可能會(huì)讓人感到沮喪,但我們可以通過創(chuàng)建通用的IdentityComparator解決類型推斷:
class Utils {static <E> Comparator<E> compare() {return (e1, e2) -> 0;} }使用上面的compare()方法,我們可以編寫以下流暢的比較器鏈:
people.sort(Utils.<Person>compare().thenComparing((p, o) -> p.lastName.compareTo(o.lastName)).thenComparing((p, o) -> p.firstName.compareTo(o.firstName)) );people.forEach(System.out::println);提取密鑰
這可以變得更好。 由于我們通常會(huì)比較兩個(gè)Comparator參數(shù)的相同POJO / DTO值,因此我們可以通過“鍵提取器”功能將它們提供給新的API。 它是這樣工作的:
people.sort(Utils.<Person>compare().thenComparing(p -> p.lastName).thenComparing(p -> p.firstName)); people.forEach(System.out::println);因此,在給定Person p我們?yōu)锳PI提供了提取例如p.lastName 。 實(shí)際上,一旦我們使用了鍵提取器,我們就可以省略我們自己的實(shí)用程序方法,因?yàn)檫@些庫(kù)還有一個(gè)comparing()方法來初始化整個(gè)鏈:
people.sort(Comparator.comparing((Person p) -> p.lastName).thenComparing(p -> p.firstName)); people.forEach(System.out::println);同樣,我們需要幫助編譯器,因?yàn)樗荒芡茢嗨蓄愋?#xff0c;即使原則上在這種情況下sort()方法將提供足夠的信息。 要了解有關(guān)Java 8的通用類型推斷的更多信息,請(qǐng)參見我們以前的博客文章 。
結(jié)論
與Java 5一樣,可以在JDK庫(kù)中看到升級(jí)的最大改進(jìn)。 當(dāng)Java 5為Comparators帶來類型安全性時(shí),Java 8使它們易于讀取和編寫(給出或接受奇數(shù)類型推理怪癖)。
Java 8將徹底改變我們編程的方式,下周,我們將看到Java 8如何影響我們與SQL交互的方式。
翻譯自: https://www.javacodegeeks.com/2014/02/java-8-friday-goodies-lambdas-and-sorting.html
總結(jié)
以上是生活随笔為你收集整理的Java 8 Friday Goodies:Lambda和排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 传小米汽车已试生产近一个月 每周50辆样
- 下一篇: 《沙丘:香料战争》即时战略游戏 9 月