Stream API 流API是Java 8引入了函数式编程的证明,Stream API提供了元素流的函数式操作,包括list、set、map等,还支持过滤filtering、映射mapping、移除集合中的重复元素等。 可以从集合、数组、读缓冲区等获取流Stream。这是目前为止最大的一次对Java库的完善,以便开发者能够写出更加有效、更加简洁和紧凑的代码。
流(Stream)仅仅代表着数据流,并没有数据结构,所以他遍历完一次之后便再也无法遍历(这点在编程时候需要注意,不像Collection,遍历多少次里面都还有数据),它的来源可以是Collection、array、io等等。
流作用是提供了一种操作大数据接口,让数据操作更容易和更快。它具有过滤、映射以及减少遍历数等方法,这些方法分两种:中间方法和终端方法,“流”抽象天生就该是持续的,中间方法永远返回的是Stream,因此如果我们要获取最终结果的话,必须使用终点操作才能收集流产生的最终结果。区分这两个方法是看他的返回值,如果是Stream则是中间方法,否则是终点方法。
中间的操作:
filter - 排除所有与断言不匹配的元素。
map - 通过Function对元素执行一对一的转换。
flatMap - 通过FlatMapper将每个元素转变为无或更多的元素。
peek - 对每个遇到的元素执行一些操作。主要对调试很有用。
distinct - 根据.equals行为排除所有重复的元素。这是一个有状态的操作。
sorted - 确保流中的元素在后续的操作中,按照比较器(Comparator)决定的顺序访问。这是一个有状态的操作。
limit - 保证后续的操作所能看到的最大数量的元素。这是一个有状态的短路的操作。
substream - 确保后续的操作只能看到一个范围的(根据index)元素。像不能用于流的String.substring一样。也有两种形式,一种有一个开始索引,一种有一个结束索引。二者都是有状态的操作,有一个结束索引的形式也是一个短路的操作。
末端的操作:
forEach - 对流中的每个元素执行一些操作。
toArray - 将流中的元素倾倒入一个数组。
reduce - 通过一个二进制操作将流中的元素合并到一起。
collect - 将流中的元素倾倒入某些容器,例如一个Collection或Map.
min - 根据一个比较器找到流中元素的最小值。
max -根据一个比较器找到流中元素的最大值。
count - 计算流中元素的数量。
anyMatch - 判断流中是否至少有一个元素匹配断言。这是一个短路的操作。
allMatch - 判断流中是否每一个元素都匹配断言。这是一个短路的操作。
noneMatch - 判断流中是否没有一个元素匹配断言。这是一个短路的操作。
findFirst - 查找流中的第一个元素。这是一个短路的操作。
findAny - 查找流中的任意元素,可能对某些流要比findFirst代价低。这是一个短路的操作。
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 package com.ehking.example.java8.newfeature.demo04;import java.util.Arrays;import java.util.Collection;import java.util.List;import java.util.Map;import java.util.stream.Collectors;public class Java8StreamsDemo { private enum Status { OPEN, CLOSED } private static final class Task { private final Status status; private final Integer points; Task(final Status status, final Integer points) { this .status = status; this .points = points; } public Integer getPoints () { return points; } public Status getStatus () { return status; } @Override public String toString () { return String.format("[%s, %d]" , status, points); } } public static void main (String[] args) { final Collection<Task> tasks = Arrays.asList( new Task (Status.OPEN, 5 ), new Task (Status.OPEN, 13 ), new Task (Status.CLOSED, 8 ) ); final long totalPointsOfOpenTasks = tasks .stream() .filter(task -> task.getStatus() == Status.OPEN) .mapToInt(Task::getPoints) .sum(); System.out.println("Total points: " + totalPointsOfOpenTasks); final double totalPoints = tasks .stream() .parallel() .map(task -> task.getPoints()) .reduce(0 , Integer::sum); System.out.println("Total points (all tasks): " + totalPoints); final Map<Status, List<Task>> map = tasks .stream() .collect(Collectors.groupingBy(Task::getStatus)); System.out.println(map); final Collection<String> result = tasks .stream() .mapToInt(Task::getPoints) .asLongStream() .mapToDouble(points -> points / totalPoints) .boxed() .mapToLong(weigth -> (long ) (weigth * 100 )) .mapToObj(percentage -> percentage + "%" ) .collect(Collectors.toList()); System.out.println(result); } }