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. 函数式接口

  • 接口中有且仅有一个抽象方法

  • 常见接口

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);

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值