一种支持顺序和并行聚合操作的元素序列,能够对集合、数组进行过滤、排序、去重等操作;
Stream流与日常IO流是不同的技术体系;
官方定义:
| A sequence of elements supporting sequential and parallel aggregate operations. |
Stream的两种操作:
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon"); |
| |
| Stream<String> namesOfStartsWithJ = names.filter(item -> item.startsWith("j")); |
| |
| namesOfStartsWithJ.forEach(System.out::println); |
| } |
| } |
| |
2. Stream的创建方式
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| String[] names = {"tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon"}; |
| |
| Stream<String> namesOfStream = Arrays.stream(names); |
| } |
| } |
| |
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| String[] names = {"tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon"}; |
| List<String> nameList = Arrays.asList(names); |
| |
| Stream<String> namesOfStream1 = nameList.stream(); |
| Stream<String> namesOfStream2 = nameList.parallelStream(); |
| } |
| } |
| |
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| |
| Stream<String> namesOfStream1 = Stream.of("tom"); |
| Stream<String> namesOfStream2 = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon"); |
| |
| Stream<Integer> namesOfStream3 = Stream.iterate(1, item -> item + 1); |
| Stream<Integer> namesOfStream4 = Stream.generate(() -> new Random().nextInt(100)); |
| |
| Stream<Integer> namesOfStream5 = Stream.empty(); |
| } |
| } |
| |
3. Stream的中间操作
- 过滤
- filter:对元素进行过滤;
- distinct:对元素进行去重,必须重写元素的hashCode()和equals()方法;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| names.filter(item -> item.startsWith("j")) |
| |
| .distinct() |
| .forEach(System.out::println); |
| } |
| } |
| |
- 切片
- limit:截取前面n个元素;
- skip:跳过前面n个元素,当流中元素个数不足n个时,将返回一个空流;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| names.limit(3) |
| |
| .skip(2) |
| .forEach(System.out::println); |
| } |
| } |
| |
- 映射
- map:对元素进行操作,转换为另一种类型;
- flatMap:对元素进行操作,转换为一种Stream流;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack"); |
| |
| names.map(User::new).forEach(System.out::println); |
| } |
| } |
| |
| class User { |
| private String name; |
| |
| public User(String name) { |
| this.name = name; |
| } |
| |
| @Override |
| public String toString() { |
| return "User: {name=" + name + "}"; |
| } |
| } |
| |
| |
| User: {name=tom} |
| User: {name=jerry} |
| User: {name=jack} |
| |
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Integer[] arr1 = {1, 2, 3}; |
| Integer[] arr2 = {4, 5, 6}; |
| Integer[] arr3 = {7, 8, 9}; |
| Stream<Integer[]> stream = Stream.of(arr1, arr2, arr3); |
| |
| stream.flatMap(Arrays::stream).forEach(System.out::println); |
| } |
| } |
| |
- 排序
- sorted:若元素实现了Comparable接口,重写了compareTo方法,则采用元素内部的方法比较,否则需要传入自定义的比较函数;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| names.sorted().forEach(System.out::println); |
| } |
| } |
| |
| |
| bob |
| jack |
| jack |
| jerry |
| jon |
| kevin |
| lisa |
| mark |
| tom |
4. Stream的终止操作
- 查找
- findFirst:返回第一个元素,注意不是直接返回的元素对象,而是被Optional容器包装的元素对象;
- findAny:返回任意一个元素,注意也是返回的被Optional容器包装的元素对象;
- max:返回元素中的最大值,需要传入比较函数,注意也是返回的被Optional容器包装的元素对象;
- min:返回元素中的最小值,需要传入比较函数,注意也是返回的被Optional容器包装的元素对象;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6); |
| Optional<Integer> first = stream1.findFirst(); |
| System.out.println("first: " + first.get()); |
| |
| Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5, 6); |
| Optional<Integer> any = stream2.findAny(); |
| System.out.println("any: " + any.get()); |
| |
| Stream<Integer> stream3 = Stream.of(1, 2, 3, 4, 5, 6); |
| Optional<Integer> max = stream3.max(Integer::compareTo); |
| System.out.println("max: " + max.get()); |
| |
| Stream<Integer> stream4 = Stream.of(1, 2, 3, 4, 5, 6); |
| Optional<Integer> min = stream4.min(Integer::compareTo); |
| System.out.println("min: " + min.get()); |
| } |
| } |
| |
| // 运行结果 |
| first: 1 |
| any: 1 |
| max: 6 |
| min: 1 |
| |
-
匹配
-
allMatch:是否所有元素都匹配;
-
anyMatch:是否有任意一个元素匹配;
-
noneMatch:是否所有元素都不匹配;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> stream1 = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| boolean result1 = stream1.allMatch(item -> item.length() < 6); |
| System.out.println("result1: " + result1); |
| |
| Stream<String> stream2 = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| boolean result2 = stream2.anyMatch(item -> item.contains("z")); |
| System.out.println("result2: " + result2); |
| |
| Stream<String> stream3 = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| boolean result3 = stream3.noneMatch(item -> item.startsWith("b")); |
| System.out.println("result3: " + result3); |
| } |
| } |
| |
| // 运行结果 |
| result1: true |
| result2: false |
| result3: false |
| |
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| long size = names.filter(item -> item.startsWith("j")).count(); |
| System.out.println("size: " + size); |
| } |
| } |
| |
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob", "kevin", "jon", "jack"); |
| |
| names.filter(item -> item.startsWith("j")).forEach(System.out::println); |
| } |
| } |
| |
- 聚合
- reduce:按照自定义规则对元素进行聚合操作,并返回期待的结果;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<Integer> stream1 = Stream.iterate(1, item -> item + 1); |
| |
| Optional<Integer> sum1 = stream1.limit(100).reduce(Integer::sum); |
| System.out.println("sum1: " + sum1.get()); |
| |
| Stream<Integer> stream2 = Stream.iterate(1, item -> item + 1); |
| |
| Integer sum2 = stream2.limit(100).reduce(100, Integer::sum); |
| System.out.println("sum2: " + sum2); |
| } |
| } |
| |
| // 运行结果 |
| sum1: 5050 |
| sum2: 5150 |
| |
- 收集
- collect:将已操作过的元素收集起来,可返回List、Set、Map等等;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<Integer> stream1 = Stream.iterate(1, item -> item + 1); |
| |
| List<Integer> evenNumbers = stream1.limit(10) |
| .filter(item -> item % 2 == 0) |
| .collect(Collectors.toList()); |
| System.out.println("偶数: " + evenNumbers); |
| |
| Stream<Integer> stream2 = Stream.iterate(1, item -> item + 1); |
| |
| Map<String, List<Integer>> numberMap = stream2.limit(10) |
| .collect( |
| Collectors.toMap( |
| item -> item % 2 == 0 ? "偶数" : "奇数", |
| item -> { |
| List<Integer> list = new ArrayList<>(); |
| list.add(item); |
| return list; |
| }, |
| (oldList, newList) -> { |
| newList.addAll(oldList); |
| return newList; |
| } |
| ) |
| ); |
| System.out.println("奇偶数分类: " + numberMap); |
| } |
| } |
| |
| // 运行结果 |
| 偶数: [2, 4, 6, 8, 10] |
| 奇偶数分类: {偶数=[10, 8, 6, 4, 2], 奇数=[9, 7, 5, 3, 1]} |
| |
5. Stream的并行流
- Stream流可以通过实例的parallel和sequential两个方法在并行流和顺序流之间切换;
- Stream并行流是以Java7引入的fork/join框架为基础,以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> names = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob"); |
| names.parallel().filter(item -> { |
| System.out.println("filter: " + "thread=" + Thread.currentThread().getName() + ", item=" + item); |
| return item.startsWith("j"); |
| }).forEach(item -> System.out.println("result: " + item)); |
| } |
| } |
| |
| // 运行结果 |
| filter: thread=main, item=lisa |
| filter: thread=ForkJoinPool.commonPool-worker-2, item=bob |
| filter: thread=main, item=tom |
| filter: thread=ForkJoinPool.commonPool-worker-3, item=jack |
| filter: thread=ForkJoinPool.commonPool-worker-1, item=jerry |
| filter: thread=ForkJoinPool.commonPool-worker-2, item=mark |
| result: jerry |
| result: jack |
| |
6. Stream的注意事项
- Stream自己不会存储元素;
- Stream的中间操作不会改变源对象,相反它会返回一个持有结果的新Stream实例;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> stream1 = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob"); |
| Stream<String> stream2 = stream1.filter(item -> item.startsWith("j")); |
| |
| System.out.println(stream1); |
| System.out.println(stream2); |
| } |
| } |
| |
| // 运行结果 |
| java.util.stream.ReferencePipeline$Head@404b9385 |
| java.util.stream.ReferencePipeline$2@6d311334 |
| |
- Stream的中间操作是延迟加载的,只有当终止操作存在的时候,中间操作才会执行;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<String> stream1 = Stream.of("tom", "jerry", "jack", "lisa", "mark", "bob"); |
| Stream<String> stream2 = stream1.filter(item -> { |
| |
| System.out.println("filter: " + item); |
| return item.startsWith("j"); |
| }); |
| } |
| } |
| |
- Stream的执行实际上是每一个元素沿着执行链垂直移动的,也就是说当一个元素将执行链执行完成后才会开始第二个元素,但注意排序操作例外;
| public class StreamTest { |
| |
| public static void main(String[] args) { |
| Stream<Integer> stream1 = Stream.of(3, 1, 2, 5, 6, 4); |
| stream1.sorted((a, b) -> { |
| |
| System.out.println("sort: " + a + ", " + b); |
| return Integer.compare(a, b); |
| }).filter(item -> { |
| |
| System.out.println("filter: " + item); |
| return item <= 3; |
| }).map(item -> { |
| |
| System.out.println("map: " + item * 2); |
| return item * 2; |
| }).forEach(item -> { |
| |
| System.out.println("print: " + item); |
| }); |
| } |
| } |
| |
| // 运行结果 |
| sort: 1, 3 |
| sort: 2, 1 |
| sort: 2, 3 |
| sort: 2, 1 |
| sort: 5, 2 |
| sort: 5, 3 |
| sort: 6, 3 |
| sort: 6, 5 |
| sort: 4, 3 |
| sort: 4, 6 |
| sort: 4, 5 |
| filter: 1 |
| map: 2 |
| print: 2 |
| filter: 2 |
| map: 4 |
| print: 4 |
| filter: 3 |
| map: 6 |
| print: 6 |
| filter: 4 |
| filter: 5 |
| filter: 6 |
| |
- Stream的实例在执行终止操作后不能再执行其他操作,否则会抛出
stream has already been operated upon or closed
异常;
————————————————
原文链接:https://blog.csdn.net/gu19930914/article/details/115769134
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)