Stream API
java8提供了一个新的API,简称Stream。它支持多核处理器并行操作,很多思路来源于数据库的操作,可以减少很多数据库SQL操作。
在java8可以有一个更高层次的抽象,思路变成把这样的流变成那样的流,而不是一次只处理一个项目;还有一个好处,Java8可以透明的把输入的不相干部门拿到几个CPU内核上去分别执行Stream流水线操作,这些并行操作都是免费的。
- 外部迭代
List<Apple> inventory = Arrays.asList(new Apple("green", 4), new Apple("red", 55));
//过滤出青苹果
List<Apple> colorList = new ArrayList<>();
for (Apple apple : inventory) {
if (apple.getColor().equals("green")) {
colorList.add(apple);
}
}
所谓的外部迭代我的理解就是我们需要关心迭代的细节。
- 内部迭代
List<Apple> inventory = Arrays.asList(new Apple("green", 4), new Apple("red", 55));
inventory.stream().filter(apple -> apple.getColor().equals("green")).collect(Collectors.toList());
在内部迭代里面我们只是告诉它一个迭代规则,具体怎么迭代我们并不关心;而且这代码更易于阅读,少了很多干扰项。
向方法传递代码的技巧
Java8中将代码传递给方法的功能还让我们能够使用一套新技巧,通常称为函数式编程。
Java8增加了把方法作为参数传递给另一个方法,这一概念叫做行为参数化。
- 方法引用
和对象创建类型使用 Object::method 表示方法引用。
例如你需要筛选一个目录下面的所有隐藏文件。
java8之前:
File[] files = new File(".").listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isHidden();
}
});
对于这个匿名类FileFilter是不是觉得没啥用,而且还不易阅读。我们想要做的就是判断这个文件是不是隐藏文件。
Java8
File[] files = new File(".").listFiles(File::isHidden);
或者
File[] files = new File(".").listFiles(file->file.isHidden());
这也就是我们所说的传递方法,传递行为,不再仅仅是传递值了。
- Lambda
例如:
static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> test) {
List<Apple> result = inventory.stream().filter(apple -> test.test(apple)).collect(Collectors.toList());
return result;
}
Lambda 的目的使代码更清新,更干净。
接口中的默认方法
默认方法的作用是:为了支持库设计,让接口更容易改造。
例如:
List<Apple> inventory = Arrays.asList(new Apple("green", 4), new Apple("red", 55));
inventory.stream().filter(apple -> apple.getColor().equals("green")).collect(Collectors.toList());
在Java8 之前list里面并没有stream方法,它的祖先类Collection里面也没有stream方法,那它是怎么添加stream的呢?如果加在Collection里面是不是意味着它的所有子类都需要去重写stream方法,这无疑是不可能的。
Java8 的做法是:接口如今可以包含实现类没有提过实现的方法签名,缺失的方法主体随接口提供。在Java8的接口声明中使用新的default关键字来表示这一点。