Java8 常用的Stream流操作

原文链接

概念:Steam 是Java8 提出的一个新概念,不是输入输出的 Stream 流,而是一种用函数式编程方式在集合类上进行复杂操作的工具。简而言之,是以内部迭代的方式处理集合数据的操作,内部迭代可以将更多的控制权交给集合类。Stream 和 Iterator 的功能类似,只是 Iterator 是以外部迭代的形式处理集合数据的操作。

在Java8以前,对集合的操作需要写出处理的过程,如在集合中筛选出满足条件的数据,需要一 一遍历集合中的每个元素,再把每个元素逐一判断是否满足条件,最后将满足条件的元素保存返回。而Stream 对集合筛选的操作提供了一种更为便捷的操作,只需将实现函数接口的筛选条件作为参数传递进来,Stream会自行操作并将合适的元素同样以stream 的方式返回,最后进行接收即可。

2种操作:

1.intermediate  operation 中间操作:中间操作的结果是刻画、描述了一个Stream,并没有产生一个新集合,这种操作也叫做惰性求值方法。

2.terminal operation 终止操作:最终会从Stream中得到值。

如何区分这2种操作呢?可以根据操作的返回值类型判断,如果返回值是Stream,则该操作是中间操作,如果返回值是其他值或者为空,则该操作是终止操作。

如下图的前2个操作是中间操作,只有最后一个操作是终止操作。


可以形象地理解Stream的操作是对一组粗糙的工艺品原型(即对应的 Stream 数据源)进行加工成颜色统一的工艺品(即最终得到的结果),第一步筛选出合适的原型(即对应Stream的 filter 的方法),第二步将这些筛选出来的原型工艺品上色(对应Stream的map方法),第三步取下这些上好色的工艺品(即对应Stream的 collect(toList())方法)。在取下工艺品之前进行的操作都是中间操作,可以有多个或者0个中间操作,但每个Stream数据源只能有一次终止操作,否则程序会报错。

常用的 Stream 流操作:

1.collect(toList()) 终止操作

由Stream中的值生成一个List列表,也可用collect(toSet())生成一个Set集合。

例:取 Stream 中每个字符串并放入一个新的列表,


  
  
  1. @Test
  2. public void collectToList() {
  3. String[] testStrings = { "java", "react", "angular", "vue" };
  4. List<String> list = Stream.of(testStrings).collect(Collectors.toList());
  5. for ( int i = 0, length = list.size(); i < length; i++) {
  6. System.out.println(list.get(i));
  7. }
  8. }

2.map 中间操作

将一种类型的值映射为另一种类型的值,可以将 Stream 中的每个值都映射为一个新的值,最终转换为一个新的 Stream 流。


例:把 Stream 中每个字符串都转换为大写的形式,


  
  
  1. @Test
  2. public void mapTest() {
  3. String[] testStrings = { "java", "react", "angular", "vue" };
  4. List<String> list = Stream.of(testStrings).map(test -> test.toUpperCase()).collect(Collectors.toList());
  5. list.forEach(test -> System.out.println(test));
  6. }
3.filter 中间操作

遍历并筛选出满足条件的元素形成一个新的 Stream 流。


例:筛选出以 j 字母开头的元素个数,此例中的count方法也是终止操作,是为了计算出 Stream 中的元素个数,


  
  
  1. @Test
  2. public void filterTest() {
  3. List<String> list = Arrays.asList( "java", "react", "angular", "javascript", "vue");
  4. long count = list.stream().filter(p -> p.startsWith( "j")).count();
  5. System.out.println(count);
  6. }
4.flatMap 中间操作

可用 Stream 替换值,并将多个 Stream 流合并成一个 Stream 流。


例:将含有一串数字的两个流合并为一个流,


  
  
  1. @Test
  2. public void flapMapTest() {
  3. List<Integer> list = (List<Integer>) Stream.of(Arrays.asList( 1, 2, 3, 4, 5, 6), Arrays.asList( 8, 9, 10, 11, 12))
  4. .flatMap(test -> test.stream()).collect(Collectors.toList());
  5. for ( int i = 0, length = list.size(); i < length; i++) {
  6. System.out.println(list.get(i));
  7. }
  8. }
5.max 、min 终止操作

求 Stream 中的最大值、最小值。

例:取出 Stream 中最长的字符串


  
  
  1. @Test
  2. public void maxTest() {
  3. String[] testStrings = { "java", "react", "angular", "javascript", "vue" };
  4. Optional<String> max = Stream.of(testStrings).max((p1, p2) -> Integer.compare(p1.length(), p2.length()));
  5. System.out.println(max);
  6. }
6.reduce 终止操作

从 Stream 的一组值中生成另一个值。


例:上述的max、min、count 实际上都是 reduce 操作,求出 Stream 元素数值的总和,


  
  
  1. @Test
  2. public void reduceSumTest() {
  3. int sum = Stream.of( 5, 6, 7, 8).reduce( 0, (accumulator, element) -> accumulator + element);
  4. System.out.println(sum);
  5. }

reduce方法的第一个参数值 0 是初始值,第二个lambda表达式参数 (accumulator, element) -> accumulator + element 是执行求和操作,其中 accumulator 是累加器,element 是每次迭代的当前元素数值。

注意:Stream 流操作远不止以上介绍的几种,这里只介绍流操作的认识和几个简单实现,更多的流操作可查阅 API 官方文档,灵活结合 lambda 表达式和 Stream 操作可以更愉快地完成常见的集合操作。


发布了11 篇原创文章 · 获赞 0 · 访问量 153

猜你喜欢

转载自blog.csdn.net/qq_37390527/article/details/105551678