Java Stream 流式处理
一、流概念
1. 结构
- 流获取
- 转换操作 : 可以有多个
- 终止操作 : 只能有一个
2. 类型
-
stream() : 单管道
-
parallelStream()
- 多管道,并行流式处理,底层使用 ForkJoinPool 实现
- 强制要求有序 : forEachOrdered()
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7); //结果:1234567 list.stream().forEach(System.out::print); //结果:5726134 list.parallelStream().forEach(System.out::print); //结果:1234567 list.parallelStream().forEachOrdered(System.out::print);
3. 函数式接口
-
接口中有且仅有一个抽象方法
-
常见接口
接口 参数 返回值 类别 Consumer T void 消费型接口 Supplier None T 供给型接口 Function T R 函数型接口 Predicate T boolean 断言型接口
4. Lambda 表达式
- 结构 : (参数) ‐> { 代码语句 }
- 用于简化 函数式接口 的编写
- 可以延迟运行,提升性能
二、流 获取
1. Collection 子接口
-
直接调用 stream() 方法
-
List
-
Set
-
Vector
List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); Set<String> set = new HashSet<>(); Stream<String> stream2 = set.stream(); Vector<String> vector = new Vector<>(); Stream<String> stream3 = vector.stream();
2. Map
-
不是 Collection 子接口,其 K-V 数据结构不符合流元素特征,所以需根据 Key、Value、Entry 分别获取
Map<String, String> map = new HashMap<>(); // ... Stream<String> keyStream = map.keySet().stream(); Stream<String> valueStream = map.values().stream(); Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
3. Array
-
数组无法添加默认方法,故使用 Stream.of() 方法获取
String[] array = { "张无忌", "张翠山", "张三丰", "张一元" }; Stream<String> stream = Stream.of(array);
二、转换 操作
1. filter( T -> boolean )
-
过滤数据,保留条件为 true 的元素
List<Integer> list = Arrays.asList(20, 23, 25, 28, 30, 33, 37, 40); //从指定数据集合中过滤出大于等于30的数据集合 List<Integer> collect = list.stream().filter(x -> x >= 30).collect(Collectors.toList()); //结果:[30, 33, 37, 40] System.out.println(collect);
2. map( T -> R )
-
转换数据,将转换后的数据存回流中
List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6"); List<Long> collect1 = list.stream().map(x -> Long.parseLong(x)).collect(Collectors.toList()); //结果:[1, 2, 3, 4, 5, 6] System.out.println(collect1); //结果:111111 list.stream().mapToInt(x -> x.length()).forEach(System.out::print); System.out.println(""); //结果:111111 list.stream().mapToLong(x -> x.length()).forEach(System.out::print); System.out.println(""); //结果:1.01.01.01.01.01.0 list.stream().mapToDouble(x -> x.length()).forEach(System.out::print);
3. flatMap( T -> Stream )
-
将流中的 元素 映射为一个 流,再把每个流连接为一个流
List<List<String>> list = new ArrayList<List<String>>(){{ add(Lists.newArrayList("a","b","c")); add(Lists.newArrayList("d","e","f")); add(Lists.newArrayList("j","k","y")); }}; //结果:[[a, b, c], [d, e, f], [j, k, y]] System.out.println(list); List<String> collect = list.stream().flatMap(List::stream).collect(Collectors.toList()); //结果:[a, b, c, d, e, f, j, k, y] System.out.println(collect);
4. distinct()
-
元素去重,底层使用 equals() 方法做比较
List<String> list = Arrays.asList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); List<String> collect = list.stream().distinct().collect(Collectors.toList()); //结果:[a, b, ab, abc, abcd, bd] System.out.println(collect);
5. sorted( T -> boolean )
-
元素排序,需事前 实现 Comparable 接口 或 自定义比较器
List<Integer> list = Arrays.asList(5, 3, 7, 1, 4, 6); List<Integer> collect = list.stream().sorted((a, b) -> a.compareTo(b)).collect(Collectors.toList()); //结果:[1, 3, 4, 5, 6, 7] System.out.println(collect);
6. limit( num )
-
限制返回的元素个数
List<String> list = Arrays.asList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); List<String> collect = list.stream().limit(3).collect(Collectors.toList()); //结果:[a, b, ab] System.out.println(collect);
7. skip( num )
-
跳过元素
List<String> list = Arrays.asList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); List<String> collect = list.stream().skip(5).collect(Collectors.toList()); //结果:[ab, a, abcd, bd, abc] System.out.println(collect);
8. peek( T -> void )
-
挑出元素进行操作,但操作后的元素不返回到流中
List<String> list = Arrays.asList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); //结果:abababcaabaabcdbdabc list.stream().peek(x -> x.toUpperCase()).forEach(System.out::print); //结果:ABABABCAABAABCDBDABC list.stream().map(x -> x.toUpperCase()).forEach(System.out::print);
三、终止 操作
1. forEach
-
forEach : 支持并行处理
-
forEachOrdered : 强制要求有序处理,速度较慢
List<String> list = Arrays.asList("a", "b", "ab"); //结果:a b ab list.stream().forEach(x -> System.out.print(x+' ')); System.out.println(""); //可以简化 //结果:a b ab list.forEach(x -> System.out.print(x+' ')); System.out.println(""); //结果:a b ab list.stream().forEachOrdered(x -> System.out.print(x+' '));
2. collect
-
toMap : 将 数据流 转换成 Map,里面包含的元素是 key / value 形式
-
toSet : 将 数据流 转换成 Set,里面包含的 元素不可重复
-
toList : 将 数据流 转换成 List,里面包含的 元素有序
-
joining : 元素间 拼接 分割符,并返回 字符串
-
groupingBy : 分组,可以将 List 转换成 Map
-
couting : 统计 元素数量
-
maxBy : 获取 最大的元素
-
minBy : 获取 最小的元素
-
summarizingInt : 汇总 Integer 类型的元素,返回 IntSummaryStatistics,可再调用具体方法进行统计
- getCount : 统计数量
- getSum : 求和
- getMin : 获取最小值
- getMax : 获取最大值
- getAverage : 获取平均值
-
summarizingLong : 汇总 Long 类型元素,用法同 summarizingInt
-
summarizingDouble : 汇总 Double 类型元素,用法同 summarizingInt
-
averagingInt : 获取 Integer 元素平均值,返回一个 Double 类型数据
-
averagingLong : 获取 Long 元素平均值,返回一个 Double 类型数据
-
averagingDouble : 获取 Double 元素平均值,返回一个 Double 类型数据
-
mapping : 获取映射,可以将原始元素的一部分内容作为一个新元素返回
List<String> list0 = Arrays.asList("a", "b", "ab"); Map<String, String> collect0 = list0.stream().collect(Collectors.toMap(String::new, Function.identity())); //结果:{ab=ab, a=a, b=b} System.out.println(collect0); List<String> list = Arrays.asList("a", "b", "ab", "a", "b", "ab"); List<String> collect1 = list.stream().collect(Collectors.toList()); //结果:[a, b, ab, a, b, ab] System.out.println(collect1); //结果:[a, ab, b] Set<String> collect2 = list.stream().collect(Collectors.toSet()); System.out.println(collect2); String collect3 = list.stream().collect(Collectors.joining(",")); //结果:a,b,ab,a,b,ab System.out.println(collect3); Map<String, Long> collect4 = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); //结果:{ab=2, a=2, b=2} System.out.println(collect4); Long collect = list.stream().collect(Collectors.counting()); //结果:6 System.out.println(collect); List<Integer> list1 = Arrays.asList(1, 3, 5, 7, 9, 11); Integer collect5 = list1.stream().collect(Collectors.maxBy((a, b) -> a.compareTo(b))).orElse(null); System.out.println(collect5); //结果:11 System.out.println(collect5); String collect6 = list1.stream().collect(Collectors.minBy((a, b) -> a.compareTo(b))).orElse(null); //结果:1 System.out.println(collect6); List<String> list2 = Arrays.asList("2", "3", "5"); IntSummaryStatistics summaryStatistics = list2.stream().collect(Collectors.summarizingInt(x -> Integer.parseInt(x))); long sum = summaryStatistics.getSum(); //结果:10 System.out.println(sum); Double collect7 = list2.stream().collect(Collectors.averagingInt(x -> Integer.parseInt(x))); //结果:3.3333333333333335 System.out.println(collect7); List<User> userList = new ArrayList<User>() {{ add(new User("jack",23)); add(new User("james",30)); add(new User("curry",28)); }}; List<String> collect8 = userList.stream().collect(Collectors.mapping(User::getName, Collectors.toList())); //[jack, james, curry] System.out.println(collect8);
3. find
-
findFirst : 查找第一个元素,返回的类型为 Optional
-
findAny : 一般返回第一个元素,返回的类型为 Optional,但如果是并行情况,则不保证是第一个
List<String> lst1 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya"); List<String> lst2 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya"); Optional<String> findFirst = lst1.parallelStream().filter(s -> s.startsWith("D")).findFirst(); Optional<String> fidnAny = lst2.parallelStream().filter(s -> s.startsWith("J")).findAny(); System.out.println(findFirst.get()); // 总是打印出 David System.out.println(fidnAny.get()); // 会随机打印出 Jack/Jill/Julia
4. match
-
allMatch : 所有元素都满足条件,返回 boolean 类型
-
anyMatch : 任意一个元素满足条件,返回 boolean 类型
-
noneMatch : 所有元素都不满足条件,返回 boolean 类型
List<Integer> list = Arrays.asList(2, 3, 5, 7); boolean allMatch = list.stream().allMatch(x -> x > 1); //结果:true System.out.println(allMatch); boolean allMatch2 = list.stream().allMatch(x -> x > 2); //结果:false System.out.println(allMatch2); boolean anyMatch = list.stream().anyMatch(x -> x > 2); //结果:true System.out.println(anyMatch); boolean noneMatch1 = list.stream().noneMatch(x -> x > 5); //结果:false System.out.println(noneMatch1); boolean noneMatch2 = list.stream().noneMatch(x -> x > 7); //结果:true System.out.println(noneMatch2);
5. count
-
统计数量,返回 long 类型,与集合的 size() 方法类似
List<String> list = Arrays.asList("a", "b", "ab"); long count = list.stream().count(); //结果:3 System.out.println(count);
6. max、min
-
max : 获取最大值,返回 Optional 类型
-
min : 获取最小值,返回 Optional 类型
List<Integer> list = Arrays.asList(2, 3, 5, 7); Optional<Integer> max = list.stream().max((a, b) -> a.compareTo(b)); //结果:7 System.out.println(max.get()); Optional<Integer> min = list.stream().min((a, b) -> a.compareTo(b)); //结果:2 System.out.println(min.get());
7. reduce
-
规约操作,将整个数据流规约成一个值
-
两个参数 : 循环计算的初始值、计算累加器
-
count、max、min 底层就是使用 reduce 实现
List<Integer> list = Arrays.asList(2, 3, 5, 7); Integer sum1 = list.stream().reduce(0, Integer::sum); //结果:17 System.out.println(sum1); Optional<Integer> reduce = list.stream().reduce((a, b) -> a + b); //结果:17 System.out.println(reduce.get()); Integer max = list.stream().reduce(0, Integer::max); //结果:7 System.out.println(max); Integer min = list.stream().reduce(0, Integer::min); //结果:0 System.out.println(min); Optional<Integer> reduce1 = list.stream().reduce((a, b) -> a > b ? b : a); //2 System.out.println(reduce1.get());
8. toArray
-
数组操作,将 数据流 转换成 数组
List<String> list = Arrays.asList("a", "b", "ab"); String[] strings = list.stream().toArray(String[]::new); //结果:a b ab for (int i = 0; i < strings.length; i++) { System.out.print(strings[i]+" "); }
9. concat
-
将 两个流 合并为 一个流
Stream<String> streamA = Stream.of("张无忌"); Stream<String> streamB = Stream.of("张翠山"); Stream<String> result = Stream.concat(streamA, streamB);