🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 4-函数式编程 # 4-函数式编程 [原文链接](http://code.google.com/p/guava-libraries/wiki/FunctionalExplained) [译文链接](http://ifeve.com/google-guava-functional) 译者:沈义扬,校对:丁一 ## 注意事项 截至JDK7,Java中也只能通过笨拙冗长的匿名类来达到近似函数式编程的效果。预计JDK8中会有所改变,但Guava现在就想给JDK5以上用户提供这类支持。 过度使用Guava函数式编程会导致冗长、混乱、可读性差而且低效的代码。这是迄今为止最容易(也是最经常)被滥用的部分,如果你想通过函数式风格达成一行代码,致使这行代码长到荒唐,Guava团队会泪流满面。 比较如下代码: ``` <pre class="calibre11">``` Function<String, Integer> lengthFunction = new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } }; Predicate<String> allCaps = new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }; Multiset<Integer> lengths = HashMultiset.create( Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction)); ``` ``` 或FluentIterable的版本 ``` <pre class="calibre11">``` Multiset<Integer> lengths = HashMultiset.create( FluentIterable.from(strings) .filter(new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }) .transform(new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } })); ``` ``` 还有 ``` <pre class="calibre11">``` Multiset<Integer> lengths = HashMultiset.create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) { lengths.add(string.length()); } } ``` ``` 即使用了静态导入,甚至把Function和Predicate的声明放到别的文件,第一种代码实现仍然不简洁,可读性差并且效率较低。 截至JDK7,命令式代码仍应是默认和第一选择。不应该随便使用函数式风格,除非你绝对确定以下两点之一: - 使用函数式风格以后,整个工程的代码行会净减少。在上面的例子中,函数式版本用了11行, 命令式代码用了6行,把函数的定义放到另一个文件或常量中,并不能帮助减少总代码行。 - 为了提高效率,转换集合的结果需要懒视图,而不是明确计算过的集合。此外,确保你已经阅读和重读了Effective Java的第55条,并且除了阅读本章后面的说明,你还真正做了性能测试并且有测试数据来证明函数式版本更快。 请务必确保,当使用Guava函数式的时候,用传统的命令式做同样的事情不会更具可读性。尝试把代码写下来,看看它是不是真的那么糟糕?会不会比你想尝试的极其笨拙的函数式 更具可读性。 ## Functions\[函数\]和Predicates\[断言\] 本节只讨论直接与Function和Predicate打交道的Guava功能。一些其他工具类也和”函数式风格”相关,例如[`Iterables.concat(Iterable&lt;Iterable&gt;)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#concat%28java.lang.Iterable%29),和其他用常量时间返回视图的方法。尝试看看[2.3节的集合工具类](http://ifeve.com/google-guava-collectionutilities)。 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`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/CharMatcher.html),它通常更高效,并且在某些需求方面更有用。CharMatcher实现了Predicate<Character>,可以当作Predicate一样使用,要把Predicate转成CharMatcher,可以使用[`CharMatcher.forPredicate`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6common/base/CharMatcher.html#forPredicate%28com.google.common.base.Predicate%29)。更多细节请参考第6章-字符串处理。 此外,对可比较类型和基于比较逻辑的Predicate,Range类可以满足大多数需求——它表示一个不可变区间。Range类实现了Predicate,用以判断值是否在区间内。例如,Range.atMost(2)就是个完全合法的Predicate<Integer>。更多使用Range的细节请参照第8章。 ### 操作Functions和Predicates [Functions](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Functions.html)提供简便的Function构造和操作方法,包括: [`forMap(Map&lt;A, B&gt;)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Functions.html#forMap%28java.util.Map%29)[`compose(Function&lt;B, C&gt;, Function&lt;A, B&gt;)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Functions.html#compose%28com.google.common.base.Function,%20com.google.common.base.Function%29)[`constant(T)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Functions.html#constant%28E%29)[`identity()`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Functions.html#identity%28%29)[`toStringFunction()`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Functions.html#toStringFunction%28%29)细节请参考Javadoc。 相应地,[Predicates](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Predicates.html)提供了更多构造和处理Predicate的方法,下面是一些例子: [`instanceOf(Class)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#instanceOf%28java.lang.Class%29)[`assignableFrom(Class)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#assignableFrom%28java.lang.Class%29)[`contains(Pattern)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#contains%28java.util.regex.Pattern%29)[`in(Collection)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#in%28java.util.Collection%29)[`isNull()`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#isNull%28%29)[`alwaysFalse()`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#alwaysFalse%28%29)[`alwaysTrue()`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#alwaysTrue%28%29)[`equalTo(Object)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#equalTo%28T%29)[`compose(Predicate, Function)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#compose%28com.google.common.base.Predicate,%20com.google.common.base.Function%29)[`and(Predicate...)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#and%28com.google.common.base.Predicate...%29)[`or(Predicate...)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#or%28com.google.common.base.Predicate...%29)[`not(Predicate)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicates.html#not%28com.google.common.base.Predicate%29)细节请参考Javadoc。 ## 使用函数式编程 Guava提供了很多工具方法,以便用Function或Predicate操作集合。这些方法通常可以在集合工具类找到,如Iterables,Lists,Sets,Maps,Multimaps等。 ### 断言 断言的最基本应用就是过滤集合。所有Guava过滤方法都返回”视图”——*译者注:即并非用一个新的集合表示过滤,而只是基于原集合的视图*。 **集合类型****过滤方法**Iterable[`Iterables.filter(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#filter%28java.lang.Iterable,%20com.google.common.base.Predicate%29)[`FluentIterable.filter(Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/co%E2%80%A6common/collect/FluentIterable.html#filter%28com.google.common.base.Predicate%29)Iterator[`Iterators.filter(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#filter%28java.util.Iterator,%20com.google.common.base.Predicate%29)Collection[`Collections2.filter(Collection, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Collections2.html#filter%28java.util.Collection,%20com.google.common.base.Predicate%29)Set[`Sets.filter(Set, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#filter%28java.util.Set,%20com.google.common.base.Predicate%29)SortedSet[`Sets.filter(SortedSet, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#filter%28java.util.SortedSet,%20com.google.common.base.Predicate%29)Map[`Maps.filterKeys(Map, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#filterKeys%28java.util.Map,%20com.google.common.base.Predicate%29)[`Maps.filterValues(Map, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#filterValues%28java.util.Map,%20com.google.common.base.Predicate%29)[`Maps.filterEntries(Map, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#filterEntries%28java.util.Map,%20com.google.common.base.Predicate%29)SortedMap[`Maps.filterKeys(SortedMap, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#filterKeys%28java.util.SortedMap,%20com.google.common.base.Predicate%29)[`Maps.filterValues(SortedMap, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#filterValues%28java.util.SortedMap,%20com.google.common.base.Predicate%29)[`Maps.filterEntries(SortedMap, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#filterEntries%28java.util.SortedMap,%20com.google.common.base.Predicate%29)Multimap[`Multimaps.filterKeys(Multimap, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ommon/collect/Multimaps.html#filterKeys%28com.google.common.collect.Multimap,%20com.google.common.base.Predicate%29)[`Multimaps.filterValues(Multimap, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6mon/collect/Multimaps.html#filterValues%28com.google.common.collect.Multimap,%20com.google.common.base.Predicate%29)[`Multimaps.filterEntries(Multimap, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6on/collect/Multimaps.html#filterEntries%28com.google.common.collect.Multimap,%20com.google.common.base.Predicate%29)\*List的过滤视图被省略了,因为不能有效地支持类似get(int)的操作。请改用Lists.newArrayList(Collections2.filter(list, predicate))做拷贝过滤。 除了简单过滤,Guava另外提供了若干用Predicate处理Iterable的工具——通常在[`Iterables`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/Iterables.html)工具类中,或者是[`FluentIterable`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html)的”fluent”(链式调用)方法。 **Iterables\*\***方法签名\*\***说明****另请参见**[`boolean all(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#all%28java.lang.Iterable,%20com.google.common.base.Predicate%29)是否所有元素满足断言?懒实现:如果发现有元素不满足,不会继续迭代[`Iterators.all(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#all%28java.util.Iterator,%20com.google.common.base.Predicate%29)[`FluentIterable.allMatch(Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/co%E2%80%A6mmon/collect/FluentIterable.html#allMatch%28com.google.common.base.Predicate%29)[`boolean any(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#any%28java.lang.Iterable,%20com.google.common.base.Predicate%29)是否有任意元素满足元素满足断言?懒实现:只会迭代到发现满足的元素[`Iterators.any(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#any%28java.util.Iterator,%20com.google.common.base.Predicate%29)[`FluentIterable.anyMatch(Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/co%E2%80%A6mmon/collect/FluentIterable.html#anyMatch%28com.google.common.base.Predicate%29)[`T find(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#find%28java.lang.Iterable,%20com.google.common.base.Predicate%29)循环并返回**一个**满足元素满足断言的元素,如果没有则抛出NoSuchElementException[`Iterators.find(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#find%28java.util.Iterator,%20com.google.common.base.Predicate%29) [`Iterables.find(Iterable, Predicate, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#find%28java.lang.Iterable,%20com.google.common.base.Predicate,%20T%29) [`Iterators.find(Iterator, Predicate, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#find%28java.util.Iterator,%20com.google.common.base.Predicate,%20T%29)[`Optional&lt;T&gt; tryFind(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#tryFind%28java.lang.Iterable,%20com.google.common.base.Predicate%29)返回**一个**满足元素满足断言的元素,若没有则返回`O`ptional.absent()[`Iterators.find(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#find%28java.util.Iterator,%20com.google.common.base.Predicate%29) [`Iterables.find(Iterable, Predicate, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#find%28java.lang.Iterable,%20com.google.common.base.Predicate,%20T%29) [`Iterators.find(Iterator, Predicate, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#find%28java.util.Iterator,%20com.google.common.base.Predicate,%20T%29)[`indexOf(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#indexOf%28java.lang.Iterable,%20com.google.common.base.Predicate%29)返回第一个满足元素满足断言的元素索引值,若没有返回-1[`Iterators.indexOf(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#indexOf%28java.util.Iterator,%20com.google.common.base.Predicate%29)[`removeIf(Iterable, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#removeIf%28java.lang.Iterable,%20com.google.common.base.Predicate%29)移除所有满足元素满足断言的元素,实际调用Iterator.remove()方法[`Iterators.removeIf(Iterator, Predicate)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#removeIf%28java.util.Iterator,%20com.google.common.base.Predicate%29)### 函数 到目前为止,函数最常见的用途为转换集合。同样,所有的Guava转换方法也返回原集合的视图。 **集合类型****转换\*\***方法\*\*Iterable[`Iterables.transform(Iterable, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#transform%28java.lang.Iterable,%20com.google.common.base.Function%29)[`FluentIterable.transform(Function)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/co%E2%80%A6mmon/collect/FluentIterable.html#transform%28com.google.common.base.Function%29)Iterator[`Iterators.transform(Iterator, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html#transform%28java.util.Iterator,%20com.google.common.base.Function%29)Collection[`Collections2.transform(Collection, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Collections2.html#transform%28java.util.Collection,%20com.google.common.base.Function%29)List[`Lists.transform(List, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#transform%28java.util.List,%20com.google.common.base.Function%29)Map\*[`Maps.transformValues(Map, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#transformValues%28java.util.Map,%20com.google.common.base.Function%29)[`Maps.transformEntries(Map, EntryTransformer)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#transformEntries%28java.util.Map,%20com.google.common.collect.Maps.EntryTransformer%29)SortedMap\*[`Maps.transformValues(SortedMap, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#transformValues%28java.util.SortedMap,%20com.google.common.base.Function%29)[`Maps.transformEntries(SortedMap, EntryTransformer)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#transformEntries%28java.util.SortedMap,%20com.google.common.collect.Maps.EntryTransformer%29)Multimap\*[`Multimaps.transformValues(Multimap, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6/collect/Multimaps.html#transformValues%28com.google.common.collect.Multimap,%20com.google.common.base.Function%29)[`Multimaps.transformEntries(Multimap, EntryTransformer)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6collect/Multimaps.html#transformEntries%28com.google.common.collect.Multimap,%20com.google.common.collect.Maps.EntryTransformer%29)ListMultimap\*[`Multimaps.transformValues(ListMultimap, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6lect/Multimaps.html#transformValues%28com.google.common.collect.ListMultimap,%20com.google.common.base.Function%29)[`Multimaps.transformEntries(ListMultimap, EntryTransformer)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ect/Multimaps.html#transformEntries%28com.google.common.collect.ListMultimap,%20com.google.common.collect.Maps.EntryTransformer%29)Table[`Tables.transformValues(Table, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6common/collect/Tables.html#transformValues%28com.google.common.collect.Table,%20com.google.common.base.Function%29)\*Map和[`Multimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimap.html)有特殊的方法,其中有个[`EntryTransformer&lt;K, V1, V2&gt;`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.EntryTransformer.html)参数,它可以使用旧的键值来计算,并且用计算结果替换旧值。 \*对Set的转换操作被省略了,因为不能有效支持contains(Object)操作——*译者注:懒视图实际上不会全部计算转换后的**Set**元素,因此不能高效地支持**contains(Object)**。*请改用Sets.newHashSet(Collections2.transform(set, function))进行拷贝转换。 ``` <pre class="calibre11">``` List<String> names; Map<String, Person> personWithName; List<Person> people = Lists.transform(names, Functions.forMap(personWithName)); ListMultimap<String, String> firstNameToLastNames; // maps first names to all last names of people with that first name ListMultimap<String, String> firstNameToName = Multimaps.transformEntries(firstNameToLastNames, new EntryTransformer<String, String, String> () { public String transformEntry(String firstName, String lastName) { return firstName + " " + lastName; } }); ``` ``` 可以组合Function使用的类包括: Ordering[`Ordering.onResultOf(Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6le/common/collect/Ordering.html#onResultOf%28com.google.common.base.Function%29)Predicate[`Predicates.compose(Predicate, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Predicates.html#compose%28com.google.common.base.Predicate,%20com.google.common.base.Function%29)Equivalence[`Equivalence.onResultOf(Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6le/common/base/Equivalence.html#onResultOf%28com.google.common.base.Function%29)Supplier[`Suppliers.compose(Function, Supplier)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Suppliers.html#compose%28com.google.common.base.Function,%20com.google.common.base.Supplier%29)Function[`Functions.compose(Function, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Functions.html#compose%28com.google.common.base.Function,%20com.google.common.base.Function%29)此外,[ListenableFuture](http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained) API支持转换ListenableFuture。Futures也提供了接受[`AsyncFunction`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/AsyncFunction.html)参数的方法。AsyncFunction是Function的变种,它允许异步计算值。 [`Futures.transform(ListenableFuture, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6/Futures.html#transform%28com.google.common.util.concurrent.ListenableFuture,%20com.google.common.base.Function%29)[`Futures.transform(ListenableFuture, Function, Executor)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6/Futures.html#transform%28com.google.common.util.concurrent.ListenableFuture,%20com.google.common.base.Function,%20java.util.concurrent.Executor%29)[`Futures.transform(ListenableFuture, AsyncFunction)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6/Futures.html#transform%28com.google.common.util.concurrent.ListenableFuture,%20com.google.common.util.concurrent.AsyncFunction%29)[`Futures.transform(ListenableFuture, AsyncFunction, Executor)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6/Futures.html#transform%28com.google.common.util.concurrent.ListenableFuture,%20com.google.common.util.concurrent.AsyncFunction,%20java.util.concurrent.Executor%29)