开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情
1、引入流
流的使用一般包括三件事
- 一个数据源来执行一个查询
- 一个中间操作链,形成一条流的流水线
- 一个终端操作,执行流水线,并能生成结果
流的流水线背后的理念类似于构建器模式。在构建器模式中有一个调用链用来设置一套配置(对流来说这就是一个中间操作链),接着是调用built方法(对流来说就是终端操作)。
下面是中间操作总结
| 操作 | 返回类型 | 操作参数 | 函数描述符 |
|---|---|---|---|
| filter | Stream<T> | Predicat<T> | T -> boolean |
| map | Stream<T> | Function<T, R> | T -R |
| limit | Stream<T> | ||
| sorted | Stream<T> | Comparator<T> | (T, T) -> int |
| distinct | Stream<T> |
终端操作总结
| 操作 | 目的 |
|---|---|
| forEach | 消费流中的每个元素对其应用Lambda。这一操作返回void |
| count | 返回流中的元素的个数。这一操作返回long |
| collect | 把流归约成一个集合,比如List、Map甚至是Integer |
2、使用流
2.1 筛选和切片
筛选各异的元素
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
截断流
List<Dish> dishes = menu.stream()
.filter(d -> d.getCalories() > 300)
.limit(3)
.collect(toList());
跳过元素
List<Dish> dishes = menu.stream()
.filter(d -> d.getCalories() > 300)
.skip(2)
.collect(toList());
2.2 映射
流支持map方法,它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素。
提取菜名
List<String> dishNames = menu.stream()
.map(Dish::getName)
.collect(toList());
返回菜名的长度
List<Integer> dishNameLengths = menu.stream()
.map(Dish::getName)
.map(String::length)
.collect(toList());
2.3 查找和匹配
anyMatch
if (menu.stream().anymatch(Dish::isVegetarian)) {
System.out.println("The menu is (somewhat) vegetarian friendly!!");
}
allMatch
boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);
findAny
Optional<Dish> dish = menu.stream()
.filter(Dish::isVegetarian)
.findAny();
Optional
Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在。在上面代码中,findAny可能什么元素都没找到。Java8的库设计引入了Optional<T>,这样就不用返回众所周知容易出问题的null了。
isPresent()将在Optional饮食值的时候返回true,否则返回falseifPresent(Consumer<T> block)会在值存在的进修执行给定的代码块T get()会在值存在的时候返回值,否则抛出一个NoSuchElement异常T orElse(T other)会在值存在的时候返回值,否则返回一个默认值
menu.stream()
.filter(Dish::isVegetarian)
.findAny()
.ifPresent(d -> System.out.println(d.getName()))
findFirst
List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream()
.map(x -> x * x)
.filter(x -> x % 3 == 0)
.findFirst();
2.4 归约
求和
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
最大值
Optional<Integer> max = numbers.stream().reduce(Integer::max);
最小值
Optional<Integer> min = numbers.stream().reduce(Integer::min);