一. Stream流的基础概念
1. 什么是Stream流?
Stream是元素的序列,支持对数据源(集合、数组、I/O等)进行聚合操作。其核心特点包括:
• 不存储数据:仅通过管道传递数据,原始数据不受影响。
• 惰性求值:中间操作延迟执行,只有终端操作触发时才计算。
• 并行处理:通过parallelStream()轻松实现多线程处理。
2. 与传统集合操作的对比
• 代码简洁性:用filter、map等链式调用替代冗长的循环和临时变量。
• 性能优化:并行流自动拆分任务,充分利用多核CPU。
二. stream体验版demo
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
| package com.nianxi.streamDemo;
import java.util.ArrayList;
public class StreamDemo1 { public static void main(String[] args) { ArrayList<String> list1 = new ArrayList<>(); list1.add("张无忌"); list1.add("周芷若"); list1.add("赵敏"); list1.add("张强"); list1.add("张三丰");
list1.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
} }
|
三. Stream流的创建
- 单列集合 default Stream stream() : 返回一个顺序流 Collection接口中default方法
- 双列集合 无法直接调用stream方法,但是可以通过default方法keySet()或者values()获取单列集合,再调用stream方法
- 数组 public static Stream stream(T[] array) : 返回一个流 Arrays类中的静态方法
- 一堆零散的数据 public static Stream of(T… values) : 返回一个流 Stream类中的静态方法
1. 单列集合
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
| package com.nianxi.streamDemo;
import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.function.Consumer; import java.util.stream.Stream;
public class StreamDemo2 { public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
list.stream().forEach(s -> System.out.println(s)); } }
|
2. 双列集合
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
| package com.nianxi.streamDemo;
import java.util.HashMap;
public class StreamDemo3 { public static void main(String[] args) { HashMap<String,Integer> map = new HashMap<>(); map.put("张三",20); map.put("李四",30); map.put("王五",40); map.put("赵六",50); map.put("田七",60); map.put("孙八",70); map.keySet().stream().forEach(s -> System.out.println(s));
map.entrySet().stream().forEach(entry -> System.out.println(entry.getKey() + " : " + entry.getValue())); } }
|
3. 数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.nianxi.streamDemo;
import java.util.Arrays;
public class StreamDemo4 { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5}; Arrays.stream(arr).forEach(System.out::println);
String[] arr2 = {"a", "b", "c", "d", "e"}; Arrays.stream(arr2).forEach(System.out::println); } }
|
4. 零散数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.nianxi.streamDemo;
import java.util.stream.Stream;
public class StreamDemo5 { public static void main(String[] args) { Stream.of("张无忌", "周芷若", "赵敏", "张强", "张三丰").forEach(System.out::println); } }
|
5. 无限流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.nianxi.streamDemo;
import java.util.stream.Stream;
public class StreamDemo6 { public static void main(String[] args) { Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println); Stream.generate(Math::random).limit(10).forEach(System.out::println); } }
|
四. Stream流操作
Stream操作分为中间操作(Intermediate)和终端操作(Terminal),中间操作(返回新流,可链式调用),终端操作(触发计算,生成结果)
1. 中间操作
1. filter:对流中的数据进行过滤
2. limit:截取指定数量的数据
3. skip:跳过指定数量的数据
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
| package com.nianxi.streamDemo;
import java.util.ArrayList; import java.util.Collections; import java.util.function.Predicate; import java.util.stream.Stream;
public class StreamDemo7 { public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "殷素素","张琳","张三","王五","赵六");
System.out.println(list);
list.stream().skip(3).limit(3).forEach(System.out::println); } }
|
4. distinct:去重,根据hashcode和equals去重
5. concat :合并流
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
| package com.nianxi.streamDemo;
import java.util.ArrayList; import java.util.Collections; import java.util.stream.Stream;
public class StreamDemo8 { public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>(); Collections.addAll(list1, "张无忌", "张无忌","张无忌","张无忌","张强", "张三丰", "张翠山", "殷素素","张琳","张三","王五","赵六");
ArrayList<String> list2 = new ArrayList<>(); Collections.addAll(list2, "周芷若", "赵敏");
list1.stream().distinct().forEach(System.out::println); System.out.println("-------------------------------"); Stream.concat(list1.stream().distinct(),list2.stream()).forEach(System.out::println);
} }
|
6. map 装换流中的数据类型
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
| package com.nianxi.streamDemo;
import java.util.ArrayList; import java.util.Collections; import java.util.function.Function;
public class StreamDemo9 { public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌-15", "周芷若-30", "赵敏-35", "张强-25", "张三丰-100", "张翠山-50", "殷素素-40","张琳-29","张三-20","王五-60","赵六-45"); list.stream().map(new Function<String, Integer>() { @Override public Integer apply(String s) { String[] split = s.split("-"); String age = split[1]; return Integer.parseInt(age); } }).forEach(System.out::println);
System.out.println("-------------------------------"); list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(System.out::println); } }
|
2. 终端操作
1. void forEach(Consumer<? super T> action); 遍历
2. long count() 计数
3. toArray(IntFunction<A[]> generator) 转换为数组
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
| package com.nianxi.streamDemo;
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.function.Consumer; import java.util.function.IntFunction;
public class StreamDemo10 { public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "Java", "Python", "C++", "JavaScript", "Ruby", "Go"); list.stream().forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }); System.out.println("--------"); list.stream().forEach(s -> System.out.println(s)); System.out.println("--------"); list.stream().forEach(System.out::println);
long count = list.stream().count(); System.out.println(count); System.out.println("--------");
Object[] array = list.stream().toArray(); System.out.println(Arrays.toString(array));
String[] array1 = list.stream().toArray(new IntFunction<String[]>() { @Override public String[] apply(int value) { return new String[value]; } }); System.out.println(Arrays.toString(array1));
System.out.println("--------");
String[] array2 = list.stream().toArray(value -> new String[value]); System.out.println(Arrays.toString(array2)); System.out.println("-----------------"); list.toArray(String[]::new);
} }
|
4. collect(Collector<? super T, A, R> collector) 收集流中的元素到新的集合
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
| package com.nianxi.streamDemo;
import java.util.*; import java.util.stream.Collectors;
public class StreamDemo11 { public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌-男-15", "赵敏-女-14", "周芷若-女-16", "张三丰-男-100", "张翠山-男-40","殷素素-女-16","张璐-女-16","李二-男-17"); List<String> collect = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList()); System.out.println(collect); System.out.println("--------"); Set<String> collect1 = list.stream().filter(s -> "女".equals(s.split("-")[1])).collect(Collectors.toSet()); System.out.println(collect1); System.out.println("--------"); Map<String, Integer> collect2 = list.stream().filter(s -> "女".equals(s.split("-")[1])).collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2]))); System.out.println(collect2); } }
|
五. 自定义对象过滤收集
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
| package com.nianxi.streamDemo;
import com.nianxi.entity.Actor;
import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream;
public class StreamDemo12 { public static void main(String[] args) { ArrayList<Actor> list1 = new ArrayList<>(); ArrayList<Actor> list2 = new ArrayList<>(); Collections.addAll(list1, Actor.builder().name("男一号").age(23).build(), Actor.builder().name("男二号").age(24).build(), Actor.builder().name("男三号").age(25).build(), Actor.builder().name("男四号").age(26).build(), Actor.builder().name("男五号").age(27).build(), Actor.builder().name("男六号").age(28).build()); Collections.addAll(list2, Actor.builder().name("杨一号").age(23).build(), Actor.builder().name("杨二号").age(24).build(), Actor.builder().name("女三号").age(25).build(), Actor.builder().name("女四号").age(26).build(), Actor.builder().name("女五号").age(27).build(), Actor.builder().name("女六号").age(28).build()); Stream<Actor> limit = list1.stream().filter(actor -> actor.getName().length() == 3).limit(2); limit.forEach(System.out::println); System.out.println("==================================="); Stream<Actor> skip = list2.stream().filter(actor -> actor.getName().startsWith("杨")).skip(1); skip.forEach(System.out::println); System.out.println("==================================="); Stream<Actor> concat = Stream.concat(list1.stream(), list2.stream());
System.out.println("==================================="); concat.collect(Collectors.toList()).forEach(System.out::println); } }
|
六. 总结
Stream流的作用
结合了Lambda表达式,简化集合、数组的操作
Stream的使用步骤
- 获取Stream流对象
- 使用中间方法处理数据
- 使用终端方法处理数据
如何获取Stream流对象
- 单列集合: Collection中的默认方法stream
- 双列集合: 不能直接获取
- 数组: Arrays工具类型中的静态方法stream
- 一堆零散的数据: Stream接口中的静态方法of
常见方法
- filter,limit.skip,distinct,concat,map
- forEach,count,collet