Google Guava 快速入门 —— functional 函数式编程

Google Guava 快速入门.jpg

Guava functional 函数式编程

Guava 的函数式支持可以显著简化代码,但请谨慎使用它

本节只讨论直接与 Function 和 Predicate 打交道的Guava功能。一些其他工具类也和”函数式风格”相关,在使用过程中,会相继学习认识到。

一、Functions[函数] 和 Predicates[断言]

  • 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 实现了 Predicate<Character>,可以当作 Predicate 一样使用,要把 Predicate 转成 CharMatcher,可以使用 CharMatcher.forPredicate

此外,对可比较类型和基于比较逻辑的 PredicateRange 类可以满足大多数需求,它表示一个不可变区间。Range 类实现了 Predicate,用以判断值是否在区间内。例如:Range.atMost(2) 就是个完全合法的 Predicate<Integer>

三、操作 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 操作集合。这些方法通常可以在集合工具类找到,如 IterablesListsSetsMapsMultimaps等。

五、断言

断言的最基本应用就是过滤集合。所有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)
MapMaps.transformValues(Map, Function) 
Maps.transformEntries(Map, EntryTransformer)
SortedMapMaps.transformValues(SortedMap, Function) 
Maps.transformEntries(SortedMap, EntryTransformer)
MultimapMultimaps.transformValues(Multimap, Function) 
Multimaps.transformEntries(Multimap, EntryTransformer)
ListMultimapMultimaps.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)) 进行拷贝转换。

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 使用的类包括:

类名方法
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)

七、相关文章



未经允许请勿转载:程序喵 » Google Guava 快速入门 —— functional 函数式编程

点  赞 (1) 打  赏
分享到: