你应该更新的Java知识 Java Guava 集合
来源:互联网 发布:淘宝如何成为卖家 编辑:程序博客网 时间:2024/05/22 13:43
我们打算做要做这样一件事,给出所有有资格过五四青年节的人的名字。如果你不知道的话,有资格过五四青年节的人要年龄在14周岁到28周岁之间。
按照传统的思路,这段代码应该是这样写:
List names = new ArrayList();
for (Person person : people) {
int age = person.getAge();
if (age >= 14 && age <= 28) {
names.add(person.getName());
}
}
是不是很熟悉?这样的代码在我们的代码库中几乎随处可见。单就这段代码而言,本身没什么问题。这里只是举了一个简单的例子,但现实情况往往比这复杂得多,于是,我们经常看到一个for循环里嵌套了大量的代码。
好,新风格代码时间。这次我们还是会用到Guava,先上代码后解释:
Iterable names = transform(filter(people, isAgeQualified()), toName());
这里先介绍两个重要的函数transform和filter,这两个函数都是对一个集合中的各个元素进行操作。
transform如名所示,它把集合中的一个值转换为另一个值的函数,至于具体怎么转换,则由后面的函数定义。我们来看看toName的定义:
Function<Person, String> toNames() {
return new Function<String, Integer>() {
@Override
public boolean apply(Person person) {
return person.getName();
}
};
}
这个函数的返回值是一个Function,是的,它是一个“函数”。在Java里,函数不是一等公民,所谓一等公民指的是:
- 它可以按需创建
- 它可以在数据结构中存储
- 它可以作为实参传给一个函数
- 它可以当做一个函数的返回值
Java世界的一等公民是对象,但我们可以用对象包装函数,就像前面这样,这就是函数对象。如果你了解函数式编程,你会发现,transform接收一个函数作为它的参数,那它实际上就是一个高阶函数:
- 接收一个或多个函数做实参
- 以一个函数做返回值
在函数式编程里,最为强大的一点就是通过函数的组合,我们可以做到很多未曾想过的做法,程序的可扩展性也会出乎意料地好。
让我们继续把未介绍完的说完,接下来是filter,它表示用一个条件对集合的元素进行过滤,条件在哪?我们来看isAgeQualified的定义:
Predicate isAgeQualified() {
return new Predicate() {
@Override
public boolean apply(Person person) {
int age = person.getAge();
return age >= 14 && age <= 28;
}
};
}
Predicate实际上也是一种形式的函数,只不过,它的返回值是boolean,有了上面的基础,它也就不那么难以理解了。
好,为了体现这段程序的扩展性,我们继续扩展一下我们的需求:我们要找出所有符合条件的男同胞。如果采用的是原来的循环,那么我们通常的做法是在if里面在添加一个条件,事实上,大量复杂的for循环就是这么一点一点扩充出来的。好,我们看看按照新的做法,我们会怎么做:
Iterable names = transform(filter(people, and(isAgeQualified(), isMale()), toName());
这里新增了isMale()函数,它的实现你也可以想到:
Predicate isMale() {
return new Predicate() {
@Override
public boolean apply(Person person) {
return person.isMale();
}
};
}
这里还增加了一个and函数,它可以把多个Predicate组合起来。Guava本身给我们还提供许多这样的逻辑运算符,比如or、not等等。
一旦形成了一个函数,它最大的价值在于重用,比如,我们现在要超出一些男同胞,干些体力活,那这个函数就又可以发挥价值了。
如果你接触 Lisp 族的程序设计语言,这样的括号套括号的做法你会觉得眼熟。当我们有很多的操作要组合在一起的时候,这种写法就颇具 Lisp 风味了。之所以我们需要写成这样,很大程度是拜 Java 僵化的语法所赐,我们无法给既有类型添加方法。在一 些可以扩展类的语言里,这段代码会更流畅一些。
Guava还给我们提供了另外一种做法,既然我们不能扩展已有的类,就不妨提供一个新的类,它的名字叫做FluentIterable:
FluentIterable names = FluentIterable.from(people).filter(isAgeQualified()).transform(toName());
如果你说过反if和反for运动,看了这篇,你就应该知道怎么样消除集合操作中的一些if和for了。
- 你应该更新的Java知识 Java Guava 集合
- 你应该更新的Java知识之集合初始化
- 你应该更新的JAVA知识
- 你应该更新的 Java 知识
- 你应该更新的Java知识
- 你应该更新的Java知识之Observer
- 你应该更新的Java知识之构建工具
- 你应该更新的Java知识之Observer
- 你应该更新的Java知识之惰性求值
- 你应该更新的Java知识之Optional
- 你应该更新的Java知识之常用程序库
- 你应该更新的 Java 知识之常用程序库
- [转]你应该更新的Java知识之Optional高级用法
- 你应该更新的Java知识之常用程序库(一)
- 你应该更新的Java知识之常用程序库(二)
- 你应该更新的Java知识之构建工具:Gradle 和 Buildr
- java guava 集合的操作:交集、差集、并集
- java集合的一些知识
- 你应该更新的Java知识之集合初始化
- Eclipse的下载和安装
- C++ public class
- 当前标识(**)没有对“C:\Windows\Microsoft.NET\..\Temporary ASP.NET Files”的写访问权限
- 撒发撒反抗就撒艰苦发即可撒
- 你应该更新的Java知识 Java Guava 集合
- 找数组中第i小的元素
- 怎样使用CMenu类
- input 事件集合
- strlen和sizeof的区别
- 你应该更新的Java知识之惰性求值
- 为什么C++编译器不能支持对模板的分离式编译
- python String 的一些基本操作
- T-sql 中操作文件大全