在JDK 8 之后增加了java.util.stream包,这个Stream不同与IO的流。官方的描述”Classes to support functional-style operations on streams of elements, such as map-reduce transformations on collections.“ 支持元素流功能性操作的类,例如集合上的map-reduce转换。

Stream API 引入的目的是支持函数式的操作,比如在集合上面很多的业务都是相关的,例如排序、求最大值等,既然都有这样的操作,那么就可以抽取出来,进行连续的操作。这样的连续操作,就类似于流水的进行,也就是流式操作。

分类

流(Stream)的操作主要分成两类:
1.中间的(intermediate) :
中间的操作保持流的打开状态,并允许后续的操作。一个流可以后面跟随零个或多个 中间的(intermediate) 操作。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。

如:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

2.末端的(Terminal) :
末端的(Terminal)操作必须是对流的最终操作,一个流只能有一个 terminal 操作,当这个操作执行后。

如:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

还有一种操作被称为 short-circuiting。用以指:
对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。

如:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

操作流程

1.获取一个流
2.执行一个或者多个中间的操作
3.执行一个末端的操作

流的获取

1.对于数组

1
Arrays.stream(array)

2.对于集合Collection

1
Collection.stream()

3.对于Map
Map 本身没有流,但具有类似的操作,如:

1
2
3
map.putIfAbsent
map.computeIfPresent
map.merge

对于基本数据类中,目前具有三种对应的包装类型 Stream :IntStream、LongStream、DoubleStream

当然我们也可以用 Stream、Stream >、Stream,但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。

流的并行计算

只需要讲×.stream() 换成 *.parallelStream()

流的使用实例

以下特性是JDK 1.8 才具有的,所以需要设置JRE是在1.8的情况下:

ForEach 与 peek
forEach 是 terminal 操作,因此它执行后,Stream 的元素就被“消费”掉了,你无法对一个 Stream 进行两次 terminal 运算。相反,具有相似功能的 intermediate 操作 peek 可以达到上述目的。
Stream peek(Consumer<? super T> action)
返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。
这是一个中间操作。对于并行流管线,可以在上游操作的任何时间和任何线程中调用该元素可用的动作。 如果操作修改共享状态,则负责提供所需的同步。

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
package com.devnp.java8.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ForEachDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

List<String> strings = Arrays.asList("abc", "cbc", "bbc", "cbc", "uas","cctv", "cnc");

strings.stream().forEach(System.out::println);

System.out.println("----------------------------");

strings.stream().forEach(p -> System.out.println(p)); // Lambda 表达式

System.out.println("----------------------------");

strings.stream().peek(e -> System.out.println(e)).collect(Collectors.toList());

Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
}

}

输出结果:

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
abc
cbc
bbc
cbc
uas
cctv
cnc
----------------------------
abc
cbc
bbc
cbc
uas
cctv
cnc
----------------------------
abc
cbc
bbc
cbc
uas
cctv
cnc
Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR

Map
Stream map(Function<? super T,? extends R> mapper)
返回由给定函数应用于此流的元素的结果组成的流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.devnp.java8.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MapDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

List<Integer> numbers = Arrays.asList(1, 2, 2, 4, 5, 6, 7);

//distinct 去重
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

squaresList.stream().forEach(p -> System.out.println(p));

}

}

输出结果

1
2
3
4
5
6
1
4
16
25
36
49

Filter

Stream filter(Predicate<? super T> predicate) 返回由与此给定谓词匹配的此流的元素组成的流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.devnp.java8.stream;

import java.util.stream.Stream;

public class FilterDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

Stream<String> strings = Stream.of("one", "two", "three", "four") ;

strings.filter(p -> p.length() > 3).forEach(p -> System.out.println(p)); ;
}

}

输出结果:

1
2
three
four

limit

Stream limit(long maxSize) 返回由此流的元素组成的流,截断长度不能超过maxSize。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.devnp.java8.stream;

import java.util.stream.Stream;

public class LimitDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

Stream<String> strings = Stream.of("one", "two", "three", "four") ;

strings.limit(2).forEach(p -> System.out.println(p)); ;
}

}

输出结果:

1
2
one
two

sorted

Stream sorted() 返回由此流的元素组成的流,根据自然顺序排序。如果节点不能比较会抛出java.lang.ClassCastException
Stream sorted(Comparator<? super T> comparator) 返回由该流的元素组成的流,根据提供的比较器进行排序。

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
package com.devnp.java8.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SortedDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

List<Integer> numbers = Arrays.asList(8, 2, 1, 4, 5, 6, 7);

numbers.stream().sorted().forEach(p -> System.out.print(p + ","));

System.out.println();

List<Person> persons = new ArrayList<>();

Person person1 = new Person("ebcs", 20);
Person person2 = new Person("dfbcs", 21);
Person person3 = new Person("hbcs", 25);
Person person4 = new Person("cbcs", 18);
persons.add(person1);
persons.add(person2);
persons.add(person3);
persons.add(person4);

persons.stream().sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).forEach(p -> System.out.print(p.getName() + ","));
}

}

class Person {

private String name ;

private Integer age ;


public Person() {
super();
}

public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}


}

运行结果:

1
2
1,2,4,5,6,7,8,
cbcs,dfbcs,ebcs,hbcs,

min/max/count
Optional max(Comparator<? super T> comparator) 根据提供的比较器返回此流的最大元素。 这是减少的一个特例。
Optional min(Comparator<? super T> comparator) 根据提供的比较器返回该流的最小元素。
long count() 返回此流中的元素数。
IntStream mapToInt(ToIntFunction<? super T> mapper) 返回一个IntStream,其中包含将给定函数应用于此流的元素的结果。

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
package com.devnp.java8.stream;

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;

public class StatisticsDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

List<Integer> numbers = Arrays.asList(8, 2, 1, 4, 5, 6, 7);

IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("Max : " + stats.getMax());
System.out.println("Min : " + stats.getMin());

System.out.println("Sum : " + stats.getSum());
System.out.println("Average : " + stats.getAverage());

System.out.println("Count : " + stats.getCount());

long count = numbers.stream().count();

System.out.println("Stream count : " + count);
}

}

运行结果:

1
2
3
4
5
6
Max : 8
Min : 1
Sum : 33
Average : 4.714285714285714
Count : 7
Stream count : 7

Match
Stream 有三个 match 方法,从语义上说:
boolean anyMatch(Predicate<? super T> predicate);
allMatch:Stream 中全部元素符合传入的 predicate,返回 true

boolean allMatch(Predicate<? super T> predicate);
anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true

boolean noneMatch(Predicate<? super T> predicate);
noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true

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
package com.devnp.java8.stream;

import java.util.ArrayList;
import java.util.List;

public class MatchDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

List<Student> students = new ArrayList<>();

Student person1 = new Student("ebcs", 20);
Student person2 = new Student("dfbcs", 21);
Student person3 = new Student("hbcs", 25);
Student person4 = new Student("cbcs", 18);
students.add(person1);
students.add(person2);
students.add(person3);
students.add(person4);

boolean isAllAdult = students.stream().allMatch(p -> p.getAge() > 18);

System.out.println("All are adult? " + isAllAdult);

boolean isThereAnyChild = students.stream().anyMatch(p -> p.getAge() < 12); System.out.println("Any child? " + isThereAnyChild); boolean noChild = students.stream().noneMatch(p -> p.getAge() < 12);

System.out.println("No child? " + noChild);

}

}

class Student {

private String name ;

private Integer age ;


public Student() {
super();
}

public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

}

运行结果:

1
2
3
All are adult? false
Any child? false
No child? true

代码下载

java-hibernate-core-demo.zip