抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

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;


/**
* <p>
* java8 stream 测试
*/

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)

);

// Calculate total points of all active tasks using sum()
final long totalPointsOfOpenTasks = tasks
.stream()
.filter(task -> task.getStatus() == Status.OPEN)
.mapToInt(Task::getPoints)
.sum();

System.out.println("Total points: " + totalPointsOfOpenTasks);


// Calculate total points of all tasks
final double totalPoints = tasks
.stream()
.parallel()
.map(task -> task.getPoints()) // or map( Task::getPoints )
.reduce(0, Integer::sum);

System.out.println("Total points (all tasks): " + totalPoints);


// Group tasks by their status
final Map<Status, List<Task>> map = tasks
.stream()
.collect(Collectors.groupingBy(Task::getStatus));

System.out.println(map);


// Calculate the weight of each tasks (as percent of total points)
final Collection<String> result = tasks
.stream() // Stream< String >
.mapToInt(Task::getPoints) // IntStream
.asLongStream() // LongStream
.mapToDouble(points -> points / totalPoints) // DoubleStream
.boxed() // Stream< Double >
.mapToLong(weigth -> (long) (weigth * 100)) // LongStream
.mapToObj(percentage -> percentage + "%") // Stream< String>
.collect(Collectors.toList()); // List< String >

System.out.println(result);
}

}