一、Stream的使用
1 创建
- 通过Collection接口的实现类提供的 stream()方法,或
- 通过Arrays中的静态方法 stream()获取
- 通过Stream类中的静态方法 of()
- 无限流(迭代/生成)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/** * @Author: 郜宇博 * @Date: 2021/9/1 23:28 * 流操作 */ public class StreamTests { @Test public void test(){ //1.通过Collection接口的实现类提供的 stream()方法,或 Collection<String> list = new ArrayList<>(); list.stream(); list.parallelStream(); //2.通过Arrays中的静态方法 stream()获取 Integer[] integers = new Integer[ 10 ]; Arrays.stream(integers); //3.通过Stream类中的静态方法 of() Stream<String> stream = Stream.of( "1" , "2" ); //4.无限流 //迭代 Stream<Integer> iterate = Stream.iterate( 0 , (x) -> x + 2 ); //生成 Stream<Double> generate = Stream.generate(() -> Math.random()); } } |
1.1.1并行流parallelStream
parallelStream提供了流的并行处理,它是Stream的另一重要特性,其底层使用Fork/Join框架实现。简单理解就是多线程异步任务的一种实现。
2 步骤
- 创建Stream;
- 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换);
- 对Stream进行聚合(Reduce)操作,获取想要的结果;
二、Stream的特性
惰性求值:
多个中间操作
可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理!而是在终止操作时一次性全部处理,这种情况称为“惰性求值”。
三、中间操作
筛选与切片】
1 filter()
接受lambda表达式,从流中排除某些元素
1
2
3
4
5
6
7
8
9
10
11
|
@Test public void test2(){ //获取一个数组 ArrayList<Integer> arrayList = new ArrayList<>(); for ( int i = 0 ; i < 10 ; i++) { arrayList.add(i); } //流操作:获取大于5的 arrayList.stream().filter((num)->num> 5 ).forEach(System.out::println); } //结果: 6 7 8 9 |
2 limit()
截断流,使其元素个数不超过一定数量
满足limit的数量后,就短路,不在执行后续操作
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Test public void test2(){ //获取一个数组 ArrayList<Integer> arrayList = new ArrayList<>(); for ( int i = 0 ; i < 10 ; i++) { arrayList.add(i); } //流操作:获取大于5的 arrayList.stream().filter((num)->num> 5 ) .limit( 2 ) .forEach(System.out::println); } //结果: 6 7 |
3 skip()
跳过元素,跳过前n个元素,执行后面的元素,如果不足n个则返回空流
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
|
@Test public void test2(){ //获取一个数组 ArrayList<Integer> arrayList = new ArrayList<>(); for ( int i = 0 ; i < 10 ; i++) { arrayList.add(i); } //流操作:获取大于5的 arrayList.stream().filter((num)->num> 5 ) .skip( 2 ) .forEach(System.out::println); } //结果: 8 9 3.3 map() 映射,在方法中使用方法Function< T> 函数型接口 -----> R apply(T t); @Test public void test4(){ //获取一个list List<String> list = Arrays.asList( "aaa" , "bbb" , "ccc" ); //使用流操作 转化大写 list.stream().map((str)->str.toUpperCase()) .forEach(System.out::println); } /*结果:AAA BBB CCC*/ @Test public void test3(){ //获取一个list List<String> list = Arrays.asList( "aaa" , "bbb" , "ccc" ); //流操作: 将list中的元素取出 //第一步使用map取出流,流里存放的还是流 //因此需要二次foreach Stream<Stream<Character>> chs = list.stream().map(StreamTests::getUpper); chs.forEach((stream)->{ stream.forEach(System.out::print); }); } //将str返回为流对象 public static Stream<Character> getUpper(String str){ List<Character> list = new ArrayList<>(); for (Character character: str.toCharArray()){ list.add(character); } return list.stream(); } //结果:aaabbbccc |
4 map()
映射,在方法中使用方法Function< T> 函数型接口 -----> R apply(T t);
1
2
3
4
5
6
7
8
9
10
11
|
@Test public void test4(){ //获取一个list List<String> list = Arrays.asList( "aaa" , "bbb" , "ccc" ); //使用流操作 转化大写 list.stream().map((str)->str.toUpperCase()) .forEach(System.out::println); } /*结果:AAA BBB CCC*/ |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@Test public void test3(){ //获取一个list List<String> list = Arrays.asList( "aaa" , "bbb" , "ccc" ); //流操作: 将list中的元素取出 //第一步使用map取出流,流里存放的还是流 //因此需要二次foreach Stream<Stream<Character>> chs = list.stream().map(StreamTests::getUpper); chs.forEach((stream)->{ stream.forEach(System.out::print); }); } //将str返回为流对象 public static Stream<Character> getUpper(String str){ List<Character> list = new ArrayList<>(); for (Character character: str.toCharArray()){ list.add(character); } return list.stream(); } //结果:aaabbbccc |
3.1 flatMap
相当于集合方法的 addAll
即:将流中的流内元素取出,放入一个流中,而不是流内套流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Test public void test3(){ //获取一个list List<String> list = Arrays.asList( "aaa" , "bbb" , "ccc" ); //流操作: 将list中的元素取出 //第一步使用map取出流,流里存放的还是流 //因此需要二次foreach Stream<Stream<Character>> chs = list.stream().map(StreamTests::getUpper); chs.forEach((stream)-> stream.forEach(System.out::print)); System.out.println( "\n=====" ); //方法二: //使用flatMap list.stream().flatMap(StreamTests::getUpper).forEach(System.out::print); } |
5 sorted
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
|
@Test public void test5(){ List<String> list = Arrays.asList( "aaa" , "ccc" , "bbbb" , "eeeee" ); //自然排序 list.stream() .sorted() .forEach(System.out::println); System.out.println( "=============" ); //定制排序 list.stream() .sorted((x,y)->{ //如果长度一样,则按照字典排序 if (x.length() == y.length()){ return x.compareTo(y); } //如果长度不一样则按照长度的降序排序 else { return y.length() - x.length(); } }) .forEach(System.out::println); } /*结果: aaa bbbb ccc eeeee ============= eeeee bbbb aaa ccc */ |
四、终止操作
查找与匹配
1 allMatch
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
|
Predicate<? super T> predicate /** * @Author: 郜宇博 * @Date: 2021/9/3 14:00 * 终止操作 */ public class FinalOperation { static ArrayList<Student> list; /** * allMath 检查是否全部元素符合 */ @BeforeEach public void before(){ //准备集合 Student student1 = new Student( 10 , "张三" , Student.Status.Sad); Student student2 = new Student( 20 , "李四" , Student.Status.Happy); Student student3 = new Student( 30 , "王五" , Student.Status.Free); Student student4 = new Student( 18 , "田七" , Student.Status.Free); Student student5 = new Student( 140 , "赵六" , Student.Status.Tired); list = new ArrayList<>(); list.add(student1); list.add(student2); list.add(student3); list.add(student4); list.add(student5); } } class Student{ private int age; private String name; private Status status; public int getAge() { return age; } public String getName() { return name; } public Status getStatus() { return status; } /** * 枚举状态 */ public enum Status{ Free,Tired,Happy,Sad; } public Student( int age, String name, Status status) { this .age = age; this .name = name; this .status = status; } } /** * 是否全部年龄都大于20 */ @Test public void test1(){ boolean b = list.stream().allMatch((s) -> s.getAge() > 20 ); System.out.println(b); } //结果: false |
2 anyMatch
1
2
3
4
5
6
7
8
9
10
|
Predicate<? super T> predicate /** * 是否存在年龄大于20的 */ @Test public void test2(){ boolean b = list.stream().anyMatch((s) -> s.getAge() > 20 ); System.out.println(b); } //结果:true |
3 noneMatch
1
2
3
4
5
6
7
8
9
10
11
|
Predicate<? super T> predicate /** * 是否没有满足年龄大于20的 * */ @Test public void test3(){ boolean b = list.stream().noneMatch((s) -> s.getAge() > 20 ); System.out.println(b); } //结果:false |
4 findFirst()
返回第一元素,但结果可能为null, 因此使用Optional<T> 来接收,如果为null则可以替换。
1
2
3
4
5
6
7
8
9
10
11
|
/** * 返回第一元素 */ @Test public void test4(){ Optional<Student> first = list.stream() .filter((e) -> e.getStatus().equals(Student.Status.Free)) .findFirst(); System.out.println(first); } //结果:Optional[Student{age=30, name='王五', status=Free}] |
5 findAny()
返回任意一个
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 返回任意一个 * */ @Test public void test5(){ Optional<Student> b = list.parallelStream() .filter((student -> student.getAge()< 30 )) .findAny(); System.out.println(b.get()); } //结果: 任意一个年龄小于30的学生 |
6 count
1
2
3
4
5
6
7
8
9
|
/** * 获取数量count */ @Test public void test6(){ long count = list.stream().count(); System.out.println(count); } //结果 : 5 |
7 max
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 获得最大值 */ @Test public void test7(){ Optional<Integer> max = list.stream() .map(x->x.getAge()) .max(Integer::compare); System.out.println(max.get()); } //结果: 140 |
8 min
1
2
3
4
5
6
7
8
9
10
|
/** * 获得最小值 */ @Test public void test7(){ Optional<Integer> max = list.stream() .map(x->x.getAge()) .min(Integer::compare); System.out.println(max.get()); } |
9 forEach
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Test public void test2(){ //获取一个数组 ArrayList<Integer> arrayList = new ArrayList<>(); for ( int i = 0 ; i < 10 ; i++) { arrayList.add(i); } //流操作:获取大于5的 arrayList.stream().filter((num)->num> 5 ) .limit( 2 ) .forEach(System.out::println); } //结果: 6 7 |
10 reduce
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 归纳 */ @Test public void test8(){ Integer reduce = list.stream() .map(Student::getAge) .reduce( 0 , (x, y) -> x + y); System.out.println(reduce); //方法二: //此方法有可能为null,因此封装为Optional对象 Optional<Integer> reduce1 = list.stream() .map(Student::getAge) .reduce(Integer::sum); System.out.println(reduce1.get()); } |
11 collect
可以收集为集合类,
可以在收集后进行分组、多级分组、分片
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
|
/** * 收集 */ @Test public void test9(){ List<Student> collect = list.stream().collect(Collectors.toList()); collect.forEach(System.out::println); //方式二: HashSet<Student> collect1 = list.stream().collect(Collectors.toCollection(HashSet:: new )); collect.forEach(System.out::println); } /* 结果:Student{age=10, name='张三', status=Sad} Student{age=20, name='李四', status=Happy} Student{age=30, name='王五', status=Free} Student{age=18, name='田七', status=Free} Student{age=140, name='赵六', status=Tired} */ /** * 使用收集可以计算最大值、最小值、平均值、等 * 也可以进行分组 */ @Test public void test10(){ Map<Student.Status, List<Student>> collect = list.stream().collect(Collectors.groupingBy((x) -> x.getStatus())); System.out.println(collect.size()); System.out.println(collect); } |
到此这篇关于JAVA8 Stream学习的文章就介绍到这了,更多相关JAVA8 Stream内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://www.cnblogs.com/Gao-yubo/p/15223669.html