流是Java API的新成员,它容许以声明性方式处理数据集合(经过查询语句来表达,而不是临时编写一个实现)。就如今来讲,能够把它们当作遍历数据集的高级迭代器。此外,流还能够透明地并行处理,无需写任何多线程代码了! java
流的使用通常包括三件事:数组
•一个数据源(如集合)来执行一个查询;缓存
•一个中间操做链,造成一条流的流水线;多线程
•一个终端操做,执行流水线,并能生成结果。 ide
流方法函数 |
含义ui |
示例this |
filterspa |
(中间操做)该操做会接受一个谓词(一个返回boolean的函数)做为参数,并返回一个包括全部符合谓词的元素的流。线程 |
List<Dish> vegetarianMenu = menu.stream() .filter(Dish::isVegetarian) .collect(toList()); System.out.println(vegetarianMenu); |
distinct |
(中间操做)返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流。 |
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() .filter(i -> i % 2 == 0) .distinct() .forEach(System.out::println); |
limit |
(中间操做)会返回一个不超过给定长度的流。 |
List<Dish> dishes = menu.stream() .filter(d -> d.getCalories() > 300) .limit(3) .collect(toList()); System.out.println(dishes); |
skip |
(中间操做)返回一个扔掉了前n个元素的流。 |
List<Dish> dishes = menu.stream() .filter(d -> d.getCalories() > 300) .skip(2) .collect(toList()); System.out.println(dishes); |
map |
(中间操做)接受一个函数做为参数。这个函数会被应用到每一个元素上,并将其映射成一个新的元素(使用映射一词,是由于它和转换相似,但其中的细微差异在于它是“建立一个新版本”而不是去“修改”)。 |
List<String> dishNames = menu.stream() .map(Dish::getName) .collect(toList()); System.out.println(dishNames); |
flatMap |
(中间操做)使用flatMap方法的效果是,各个数组并非分别映射成一个流,而是映射成流的内容。全部使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。 |
List<String> words = Arrays.asList("Goodbye", "World"); List<String> uniqueCharacters = words.stream() .map(w -> w.split("")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList()); System.out.println(uniqueCharacters); |
sorted |
(中间操做)返回排序后的流 |
List<String> traderStr = menu.stream() .map(transaction -> transaction.getName()) .sorted() .collect(toList()); System.out.println(traderStr); |
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); System.out.println(isHealthy); |
noneMatch |
(终端操做)能够确保流中没有任何元素与给定的谓词匹配。 |
boolean isHealthy = menu.stream() .noneMatch(d -> d.getCalories() >= 1000); System.out.println(isHealthy); |
findAny |
(终端操做)将返回当前流中的任意元素。 |
Optional<Dish> dish = menu.stream() .filter(Dish::isVegetarian) .findAny(); System.out.println(dish); |
findFirst |
(终端操做)有些流有一个出现顺序(encounter order)来指定流中项目出现的逻辑顺序(好比由List或排序好的数据列生成的流)。对于这种流,可能想要找到第一个元素。 |
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(); System.out.println(firstSquareDivisibleByThree); |
forEach |
(终端操做)遍历流 |
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() .filter(i -> i % 2 == 0) .distinct() .forEach(System.out::println); |
collect |
(终端操做)收集器 |
List<String> traderStr = menu.stream() .map(transaction -> transaction.getName()) .sorted() .collect(toList()); |
reduce |
(终端操做)归约reduce接受两个参数: •一个初始值,这里是0; •一个BinaryOperator<T>来将两个元素结合起来产生一个新值,这里咱们用的是lambda (a, b) -> a + b。 |
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); int sum = numbers.stream().reduce(0, (a, b) -> a + b); System.out.println(sum); |
count |
(终端操做)返回此流中元素的计数。 |
long evenNumbers = IntStream.rangeClosed(1, 100) .filter(n -> n % 2 == 0) .count(); System.out.println(evenNumbers); |
•可使用filter、distinct、skip和limit对流作筛选和切片。
•可使用map和flatMap提取或转换流中的元素。
•可使用findFirst和findAny方法查找流中的元素。能够用allMatch、noneMatch和anyMatch方法让流匹配给定的谓词。
•这些方法都利用了短路:找到结果就当即中止计算;没有必要处理整个流。
•能够利用reduce方法将流中全部的元素迭代合并成一个结果,例如求和或查找最大元素。
•filter和map等操做是无状态的,它们并不存储任何状态。reduce等操做要存储状态才能计算出一个值。sorted和distinct等操做也要存储状态,由于它们须要把流中的全部元素缓存起来才能返回一个新的流。这种操做称为有状态操做。
•流有三种基本的原始类型特化:IntStream、DoubleStream和LongStream。它们的操做也有相应的特化。
•流不只能够从集合建立,也可从值、数组、文件以及iterate与generate等特定方法建立。
•无限流是没有固定大小的流。
附:示例中用到的类
package lambdasinaction.chap4; import java.util.*; public class Dish { private final String name; private final boolean vegetarian; private final int calories; private final Type type; public Dish(String name, boolean vegetarian, int calories, Type type) { this.name = name; this.vegetarian = vegetarian; this.calories = calories; this.type = type; } public String getName() { return name; } public boolean isVegetarian() { return vegetarian; } public int getCalories() { return calories; } public Type getType() { return type; } public enum Type { MEAT, FISH, OTHER } @Override public String toString() { return name; } public static final List<Dish> menu = Arrays.asList( new Dish("pork", false, 800, Dish.Type.MEAT), new Dish("beef", false, 700, Dish.Type.MEAT), new Dish("chicken", false, 400, Dish.Type.MEAT), new Dish("french fries", true, 530, Dish.Type.OTHER), new Dish("rice", true, 350, Dish.Type.OTHER), new Dish("season fruit", true, 120, Dish.Type.OTHER), new Dish("pizza", true, 550, Dish.Type.OTHER), new Dish("prawns", false, 400, Dish.Type.FISH), new Dish("salmon", false, 450, Dish.Type.FISH)); }
参考:java8实战