日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Google Guava] 4-函数式编程

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Google Guava] 4-函数式编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接?譯文鏈接?譯者:沈義揚,校對:丁一

注意事項

截至JDK7,Java中也只能通過笨拙冗長的匿名類來達到近似函數式編程的效果。預計JDK8中會有所改變,但Guava現在就想給JDK5以上用戶提供這類支持。

過度使用Guava函數式編程會導致冗長、混亂、可讀性差而且低效的代碼。這是迄今為止最容易(也是最經常)被濫用的部分,如果你想通過函數式風格達成一行代碼,致使這行代碼長到荒唐,Guava團隊會淚流滿面。

比較如下代碼:

01Function<String, Integer> lengthFunction =?new?Function<String, Integer>() {
02????public?Integer apply(String string) {
03????????return?string.length();
04????}
05};
06Predicate<String> allCaps =?new?Predicate<String>() {
07????public?boolean?apply(String string) {
08????????return?CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
09????}
10};
11Multiset<Integer> lengths = HashMultiset.create(
12?????Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction));

或FluentIterable的版本

01Multiset<Integer> lengths = HashMultiset.create(
02????FluentIterable.from(strings)
03????????.filter(new?Predicate<String>() {
04????????????public?boolean?apply(String string) {
05????????????????return?CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
06????????????}
07????????})
08????????.transform(new?Function<String, Integer>() {
09????????????public?Integer apply(String string) {
10????????????????return?string.length();
11????????????}
12????????}));

還有

1Multiset<Integer> lengths = HashMultiset.create();
2for?(String string : strings) {
3????if?(CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) {
4????????lengths.add(string.length());
5????}
6}

即使用了靜態導入,甚至把Function和Predicate的聲明放到別的文件,第一種代碼實現仍然不簡潔,可讀性差并且效率較低。

截至JDK7,命令式代碼仍應是默認和第一選擇。不應該隨便使用函數式風格,除非你絕對確定以下兩點之一:

  • 使用函數式風格以后,整個工程的代碼行會凈減少。在上面的例子中,函數式版本用了11行, 命令式代碼用了6行,把函數的定義放到另一個文件或常量中,并不能幫助減少總代碼行。
  • 為了提高效率,轉換集合的結果需要懶視圖,而不是明確計算過的集合。此外,確保你已經閱讀和重讀了Effective Java的第55條,并且除了閱讀本章后面的說明,你還真正做了性能測試并且有測試數據來證明函數式版本更快。

請務必確保,當使用Guava函數式的時候,用傳統的命令式做同樣的事情不會更具可讀性。嘗試把代碼寫下來,看看它是不是真的那么糟糕?會不會比你想嘗試的極其笨拙的函數式 更具可讀性。

Functions[函數]和Predicates[斷言]

本節只討論直接與Function和Predicate打交道的Guava功能。一些其他工具類也和”函數式風格”相關,例如Iterables.concat(Iterable<Iterable>),和其他用常量時間返回視圖的方法。嘗試看看2.3節的集合工具類。

Guava提供兩個基本的函數式接口:

  • Function<A, B>,它聲明了單個方法B apply(A input)。Function對象通常被預期為引用透明的——沒有副作用——并且引用透明性中的”相等”語義與equals一致,如a.equals(b)意味著function.apply(a).equals(function.apply(b))。
  • Predicate<T>,它聲明了單個方法boolean apply(T input)。Predicate對象通常也被預期為無副作用函數,并且”相等”語義與equals一致。

特殊的斷言

字符類型有自己特定版本的Predicate——CharMatcher,它通常更高效,并且在某些需求方面更有用。CharMatcher實現了Predicate<Character>,可以當作Predicate一樣使用,要把Predicate轉成CharMatcher,可以使用CharMatcher.forPredicate。更多細節請參考第6章-字符串處理。

此外,對可比較類型和基于比較邏輯的Predicate,Range類可以滿足大多數需求——它表示一個不可變區間。Range類實現了Predicate,用以判斷值是否在區間內。例如,Range.atMost(2)就是個完全合法的Predicate<Integer>。更多使用Range的細節請參照第8章。

操作Functions和Predicates

Functions提供簡便的Function構造和操作方法,包括:

forMap(Map<A, B>)compose(Function<B, C>, Function<A, B>)constant(T)
identity()toStringFunction()?

細節請參考Javadoc。

相應地,Predicates提供了更多構造和處理Predicate的方法,下面是一些例子:

instanceOf(Class)assignableFrom(Class)contains(Pattern)
in(Collection)isNull()alwaysFalse()
alwaysTrue()equalTo(Object)compose(Predicate, Function)
and(Predicate...)or(Predicate...)not(Predicate)

細節請參考Javadoc。

使用函數式編程

Guava提供了很多工具方法,以便用Function或Predicate操作集合。這些方法通常可以在集合工具類找到,如Iterables,Lists,Sets,Maps,Multimaps等。

斷言

斷言的最基本應用就是過濾集合。所有Guava過濾方法都返回”視圖”——譯者注:即并非用一個新的集合表示過濾,而只是基于原集合的視圖。

集合類型過濾方法
IterableIterables.filter(Iterable, Predicate)FluentIterable.filter(Predicate)
IteratorIterators.filter(Iterator, Predicate)
CollectionCollections2.filter(Collection, Predicate)
SetSets.filter(Set, Predicate)
SortedSetSets.filter(SortedSet, Predicate)
MapMaps.filterKeys(Map, Predicate)Maps.filterValues(Map, Predicate)Maps.filterEntries(Map, Predicate)
SortedMapMaps.filterKeys(SortedMap, Predicate)Maps.filterValues(SortedMap, Predicate)Maps.filterEntries(SortedMap, Predicate)
MultimapMultimaps.filterKeys(Multimap, Predicate)Multimaps.filterValues(Multimap, Predicate)Multimaps.filterEntries(Multimap, Predicate)

*List的過濾視圖被省略了,因為不能有效地支持類似get(int)的操作。請改用Lists.newArrayList(Collections2.filter(list, predicate))做拷貝過濾。

除了簡單過濾,Guava另外提供了若干用Predicate處理Iterable的工具——通常在Iterables工具類中,或者是FluentIterable的”fluent”(鏈式調用)方法。

Iterables方法簽名說明另請參見
boolean all(Iterable, Predicate)是否所有元素滿足斷言?懶實現:如果發現有元素不滿足,不會繼續迭代Iterators.all(Iterator, Predicate)FluentIterable.allMatch(Predicate)
boolean any(Iterable, Predicate)是否有任意元素滿足元素滿足斷言?懶實現:只會迭代到發現滿足的元素Iterators.any(Iterator, Predicate)FluentIterable.anyMatch(Predicate)
T find(Iterable, Predicate)循環并返回一個滿足元素滿足斷言的元素,如果沒有則拋出NoSuchElementExceptionIterators.find(Iterator, Predicate)
Iterables.find(Iterable, Predicate, T default)
Iterators.find(Iterator, Predicate, T default)
Optional<T> tryFind(Iterable, Predicate)返回一個滿足元素滿足斷言的元素,若沒有則返回Optional.absent()Iterators.find(Iterator, Predicate)
Iterables.find(Iterable, Predicate, T default)
Iterators.find(Iterator, Predicate, T default)
indexOf(Iterable, Predicate)返回第一個滿足元素滿足斷言的元素索引值,若沒有返回-1Iterators.indexOf(Iterator, Predicate)
removeIf(Iterable, Predicate)移除所有滿足元素滿足斷言的元素,實際調用Iterator.remove()方法Iterators.removeIf(Iterator, Predicate)

函數

到目前為止,函數最常見的用途為轉換集合。同樣,所有的Guava轉換方法也返回原集合的視圖。

集合類型轉換方法
IterableIterables.transform(Iterable, Function)FluentIterable.transform(Function)
IteratorIterators.transform(Iterator, Function)
CollectionCollections2.transform(Collection, Function)
ListLists.transform(List, Function)
Map*Maps.transformValues(Map, Function)Maps.transformEntries(Map, EntryTransformer)
SortedMap*Maps.transformValues(SortedMap, Function)Maps.transformEntries(SortedMap, EntryTransformer)
Multimap*Multimaps.transformValues(Multimap, Function)Multimaps.transformEntries(Multimap, EntryTransformer)
ListMultimap*Multimaps.transformValues(ListMultimap, Function)Multimaps.transformEntries(ListMultimap, EntryTransformer)
TableTables.transformValues(Table, Function)

*Map和Multimap有特殊的方法,其中有個EntryTransformer<K, V1, V2>參數,它可以使用舊的鍵值來計算,并且用計算結果替換舊值。

*對Set的轉換操作被省略了,因為不能有效支持contains(Object)操作——譯者注:懶視圖實際上不會全部計算轉換后的Set元素,因此不能高效地支持contains(Object)。請改用Sets.newHashSet(Collections2.transform(set, function))進行拷貝轉換。

01List<String> names;
02Map<String, Person> personWithName;
03List<Person> people = Lists.transform(names, Functions.forMap(personWithName));
04?
05ListMultimap<String, String> firstNameToLastNames;
06// maps first names to all last names of people with that first name
07?
08ListMultimap<String, String> firstNameToName = Multimaps.transformEntries(firstNameToLastNames,
09????new?EntryTransformer<String, String, String> () {
10????????public?String transformEntry(String firstName, String lastName) {
11????????????return?firstName +?" "?+ lastName;
12????????}
13????});

可以組合Function使用的類包括:

OrderingOrdering.onResultOf(Function)
PredicatePredicates.compose(Predicate, Function)
EquivalenceEquivalence.onResultOf(Function)
SupplierSuppliers.compose(Function, Supplier)
FunctionFunctions.compose(Function, Function)

此外,ListenableFuture?API支持轉換ListenableFuture。Futures也提供了接受AsyncFunction參數的方法。AsyncFunction是Function的變種,它允許異步計算值。

Futures.transform(ListenableFuture, Function)
Futures.transform(ListenableFuture, Function, Executor)
Futures.transform(ListenableFuture, AsyncFunction)
Futures.transform(ListenableFuture, AsyncFunction, Executor)

原創文章,轉載請注明:?轉載自并發編程網 – ifeve.com本文鏈接地址:?[Google Guava] 4-函數式編程

from:?http://ifeve.com/google-guava-functional/?

總結

以上是生活随笔為你收集整理的[Google Guava] 4-函数式编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。