Guava学习之Functional Utilities

Functional Utilities

Caveats

Java 8 包含 java.util.functionjava.util.stream 包, 它取代了 Guava 的函数式编程用于该语言级别的项目。

虽然Guava 的函数式工具可以再Java 8之前的版本上使用,但是没有Java 8的函数式编程就需要使用笨拙且冗长的匿名类。

过度使用Guava的功能性编程语句会导致冗长、混乱、不可读和低效的代码。到目前为止,这些是Guava中最容易被滥用的部分(也是最常见),并且当你为了让你的代码成为“一行程序”而费尽心机时,Guava团队会流泪。

Compare the following code:

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.javaUpperCase().matchesAllOf(string); 
    } 
};
Multiset<Integer> lengths = HashMultiset.create( Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction));

or the FluentIterable version

Multiset<Integer> lengths = HashMultiset.create( 
   FluentIterable.from(strings) .filter(new Predicate<String>() { 
       public boolean apply(String string) { 
           return CharMatcher.javaUpperCase().matchesAllOf(string); 
       } 
   }) .transform(new Function<String, Integer>() { 
       public Integer apply(String string) { 
           return string.length(); 
        } 
   }));

with:

Multiset<Integer> lengths = HashMultiset.create(); 
for (String string : strings) { 
    if (CharMatcher.javaUpperCase().matchesAllOf(string)) { 
        lengths.add(string.length()); 
    }
 }

即使使用静态导入,即使和谓词声明的功能被移动到不同的文件中,第一个实现更简洁,可读性下降,效率较低。

命令式代码应该是默认的,是Java 7的首选。你不应该使用功能性语句,除非你绝对确信下列之一:

  • 使用函数式语句会节省整个项目的代码行。在上面的示例中,“功能”版本使用了11行,即命令版本6。把函数的定义移到另一个文件,或常数,是没有帮助的。
  • 为了提高效率,您需要转换后的集合的惰性计算视图,并且不能满足于显式计算的集合。此外,您已经阅读并重读了有效的Java,项目55,并且除了遵循这些指令之外,您还进行了基准测试以证明该版本更快,并且可以引用数字来证明它。

请确保,当使用Guava的功能实用程序时,传统的命令式的做事方式是不可读的。试着把它写出来。那么糟糕吗?这比你要尝试的笨拙的功能性方法更可读吗?

Functions and Predicates

本文仅讨论那些直接涉及FunctionPredicate的Guava 特征。其他一些实用程序与“函数样式”相关联,比如连接和其他在恒定时间内返回视图的方法。 尝试查看集合实用工具文章。

Guava 提供两个基础的"functional" 接口:

  • Function<A, B>, 只有一个单独的 B apply(A input)方法.  Function 实例通常被认为是透明的--无副作用 -- 以及一致性等价, , a.equals(b) 相当于 function.apply(a).equals(function.apply(b)).
  • Predicate<T>, 只有一个 boolean apply(T input)方法.  Predicate 的实例一般预期是无副作用的,并且与equal一致。

Special predicates

字符获得他们自己的Predicate专业版本, CharMatcher, 这通常是更有效和更有用的那些需求。CharMatcher 已经实现了Predicate<Character>, 并且可以相应地使用, 当 Predicate 转换为 CharMatcher 时可以使用CharMatcher.forPredicate. 细节请参考CharMatcher article .

此外,对于可比类型和基于比较的谓词,大多数需求都可以使用实现不可变间隔的Range类型来满足。范围类型实现谓词,在范围内测试包容。例如,Ranges.atMost(2)是一个完全有效的Predicate<Integer>。关于使用范围的更多细节可以在范围文章中找到。

Manipulating Functions and Predicates

Simple Function construction and manipulation methods are provided in Functions, including

Consult the Javadoc for details.

There are considerably more construction and manipulation methods available in Predicates, but a sample includes:

Consult the Javadoc for details.

Using

Guava provides many tools to manipulate collections using functions and predicates. These can typically be found in the collection utility classes Iterables, Lists, Sets, Maps, Multimaps, and the like.

Predicates

The most basic use of predicates is to filter collections. All Guava filter methods return views.

Collection type Filter methods
Iterable Iterables.filter(Iterable, Predicate)
FluentIterable.filter(Predicate)

猜你喜欢

转载自blog.csdn.net/yshuoo/article/details/83348948