Guava官方文档中文版(五)-函数式编程

函数式工具

说明

Java 8包含java.util.functionjava.util.stream包,其在该语言级别(JDK 8)取代了Guava的函数式编程类。

虽然在Java 8之前的版本Guava的函数式工具是可用的,但是在没有Java 8的函数式编程需要笨拙和冗余的使用匿名类。

过度使用Guava的函数式编程语法可能导致冗余,混乱,不可读和低效代码。这些是到目前为止Guava最容易(也是最常见的)滥用的部分。当你费尽心力编程“一行”代码时,Guava团队为之哀悼。

比较以下代码:

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));

或者FluentIterable版本

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();
       }
     }));

使用:

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

即使使用静态引入,即使Function和Predicate声明被移动到不同的文件,第一个实现不是太简洁,可读和高效的。

命令式代码应该是你的默认代码,也是从Java 7开始是你的第一选择。你不应该使用函数式语法除非你完全确定以下其中一种情况:

  • 使用函数式语法将导致节约你整个项目的代码行数。在上面的示例中,“functional”版本使用 11行,硬编码版本使用6行。将函数移动到另外一个文件,或者一个常量并没有用。
  • 为了提高效率,你需要一个转换的集合的延迟计算视图,不能满足于显性的计算集合。除此之外,你已经读过或者在读Effective Java,条目55并且除了遵循这些说明之外,你实际进行基准测试,以证明此版本更快并且可以引用数字来证明它。

请确信,当使用Guava的函数式工具,做这些事情的传统的硬式编码方式不会更加可读。试着把它写出来。有那么糟糕吗?这种方式是否比你即将尝试的荒谬和笨拙的函数方法更具有可读性?

Functions和Predicates

此主题只讨论这些直接处理FunctionPredicate的Guava特性。一些其他工具与“函数式风格”相关联,例如连接和其他方法在恒定时间内返回视图的方法。尝试到集合实用工具章节看一看。

Guava提供两个最基本的“函数式”接口:

  • Function<A, B>,它有一个单独的方法B apply(A input)Function的实例通常希望是引用透明的 – 无副作用 – 并且equels一致,也就是a.equals(b)意味着function.apply(a).equals(function.apply(b))
  • Predicate<T>,它有一个单独的方法boolean apply(T input)Predicate的实例通常希望是无任何副作用并且equals一致。
特殊的predicates

字符有他们自己的Predicate专用版本:CharMatcher,它对这些需求通常更高效,更加有用。CharMatcher已经实现Predicate<Character>并且可以相应地使用,而从PredicateCharMatcher的转换可以使用CharMatcher.forPredicate。查阅CharMatcher章节了解更多详情。

除此之外,对于可比较的类型和基于比较的predicates,大多数需求可以使用Range类型来满足,它实现了不可变间隔(interval)。Range类型实现Predicate,测试范围内的包含。例如,Range.atMost(2)是一个完美有效地Predicate<Integer>。使用range的更多细节可以在Range章节发现。

操作Functions和Predicates

简单的Function构造和操作方法在Functions中提供,包括:

查看Javadoc了解更多详情。

Predicates有非常多的构造和可用的操作方法,但是一个例子包含:

查看Javadoc了解更多详情。

使用

Guava提供许多工具通过使用functions和predicates操作集合。这些通常能在集合工具类Iterables,Lists,Sets,Maps,Multimaps等等中找到。

Predicates

predicates最基本的使用是过滤集合。所有的Guava过滤器方法返回视图:

集合类型过滤器方法
IterableIterables.filter(Iterable, Predicate),FluentIterable.filter(Predicate)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值