一、 引言

初识Stream流的作用:

需求:按照下面的要求完成集合的创建和遍历,创建一个集合,存储多个字符串元素

 通过下面代码,显然我们清晰的看到使用Stream流更为方便,而使用不同的集合遍历就有些复杂。

import java.util.ArrayList;public class Test01 {public static void main(String[] args) {ArrayList<String> list1 = new ArrayList<>();list1.add("张无忌");list1.add("周正若");list1.add("赵斌");list1.add("张强");list1.add("张三丰");// 使用 Stream 流过滤出姓“张”的并且名字长度为 3 的元素list1.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(name -> System.out.println(name)); // 张无忌、张三丰// 把所有姓“张”的元素存储到新集合中ArrayList<String> list2 = new ArrayList<>();for (String name : list1) {if (name.startsWith("张")) {list2.add(name);}}System.out.println(list2); // [张无忌, 张强, 张三丰]// 把所有姓“张”且名字长度为 3 的元素存储到新集合中ArrayList<String> list3 = new ArrayList<>();for (String name : list2) {if (name.length() == 3) {list3.add(name);}}System.out.println(list3); // [张无忌, 张三丰]}
}

二、 Stream流概述

例如上面的小例子,Stream流的思想如下:

顺序筛选

 Stream流的作用:

结合了Lambda表达式,简化集合、数字的操作。

三、Stream流的使用步骤

  1. 先得到一条Stream流(流水线),并把数据放上去。
  2. 使用中间方法对流水线上的数据进行操作。
  3. 使用终结方法对流水线上的数据进行操作。
过滤、转换 中间方法 方法调用完毕之后,还可以调用其他方法
统计、打印 终结方法 最后一步,调用完毕之后,不能调用其他方法

1.  获取Stream流

获取方式 方法名 说明
单列集合 default  Stream<E>  stream() Collection中的默认方法
双列集合

无法直接使用stream流,需要通过keySet()或者entrySet()变成单列集合

数组 public  static <T>  Stream <T>  stream(T [ ] array) Arrays工具类中的静态方法
一堆零散数据 public  static <T>  Stream <T>  of(T... values) stream接口中的静态方法

1.1  单列集合

public class StreamTest {public static void main(String[] args) {
//单列集合获取Stream流ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "a","b","c","d","e");
//获取到一个流水线,并把集合中的数据方法流水线上
//Stream<String> stream1 = list.stream();
//使用终结方法打印流水线上数据//
stream1.forEach( s ->System.out.println(s) );
list.
stream().
forEach(s -> System.out.println(s));
}
}

1.2  双列集合

public class StreamTest {public static void main(String[] args) {
//双列集合获取Stream流
//1. 创建双列集合
HashMap<String, Integer> hm = new HashMap<>();
//2. 添加数据
hm.put("aaa", 111);
hm.put("bbb", 222);
hm.put("ccc", 333);
//3.1 获取Stream流方法一: keySet()//键
hm.keySet().stream().forEach(s -> System.out.println(s));
//3.2 获取Stream流方法二:entrySet()//键值对
hm.entrySet().stream().forEach(s -> System.out.println(s));
}
}

1.3  数组

Stream接口中静态方法of的细节:

  • 方法的形参是一个可变参数,可以传递一堆零散数据,也可以传递数组。
  • 但是数组必须是引用数据类型。
  • 如果传递的是基本数据类型,是会把整个数组相当做一个元素,放到一个stream流当中。
import java.util.Arrays;
import java.util.stream.Stream;public class StreamTest {public static void main(String[] args) {// 1. 通过基本数据类型数组获取 Stream 流int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};Arrays.stream(arr1).forEach(s -> System.out.println(s));// 2. 通过引用数据类型数组获取 Stream 流String[] arr2 = {"a", "b", "c"};Arrays.stream(arr2).forEach(s -> System.out.println(s));// 3. 通过 Stream 接口中静态方法 of 获取 Stream 流// of 方法的形参是一个可变参数,可以传递一堆零散数据,也可以传递数组// 但是数组必须是引用数据类型,如果传递的是基本数据类型,会把整个数组作为一个元素放到一个流当中Stream.of(arr2).forEach(s -> System.out.println(s));Stream.of(1, 2, 3, 4, 5).forEach(s -> System.out.println(s));}
}

1.4  零散数据

细节: 一堆零散数据需要是相同的数据类型。

public class StreamTest {public static void main(String[] args) {
//零散数据获取Stream流
//基本数据类型
Stream.of(1,2,3,4,5).forEach(s -> System.out.println(s));
//引用数据类型
Stream.of("a","b","c","d","e").forEach(s -> System.out.println(s));}
}

2. Stream流的中间方法

方法名称 说明
Stream<T> filter ( Predicate<? super T>  predicate ) 过滤
Stream<T> limit ( long  maxSize) 获取前几个元素
Stream<T> skip ( long  n ) 跳过前几个元素
Stream<T> distinct ( ) 元素去重,依赖(hashCode和equals方法)
static <T> Stream<T> concat ( Stream a ,  Stream b ) 合并a和b两个流为一个流
Stream<R> map ( Function<T ,R>  mapper ) 转换流中的数据类型

注意一:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程。

注意二:修改Stream流中的数据,不会影响原来集合或者数组中的数据。

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;public class StreamTest01 {public static void main(String[] args) {//1. 过滤: 把开头的留下,其余数据过滤不要ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三", "李四", "王五", "赵六", "张七");ArrayList<String> list2 = new ArrayList<>();Collections.addAll(list2, "张三", "李四", "王五", "赵六", "张三");ArrayList<String> list3 = new ArrayList<>();Collections.addAll(list3, "孙七", "钱八");ArrayList<String> list4 = new ArrayList<>();Collections.addAll(list4, "张三-23", "李四-24", "王五-25");list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return s.startsWith("张");}}).forEach(s -> System.out.println(s)); // 张三 张七list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));//2. 获取前几个元素list.stream().limit(3).forEach(s -> System.out.println(s)); // 张三 李四 王五//3. 跳过list.stream().skip(4).forEach(s -> System.out.println(s)); // 张七//4. 去重list2.stream().distinct().forEach(s -> System.out.println(s)); // 张三 李四 王五 赵六//5. 合并Stream.concat(list2.stream(), list3.stream()).forEach(s -> System.out.println(s));//6. 转换数据类型,只能获取集合里面的年龄并打印// 第一个类型:流中原本的数据类型// 第二个类型:将要转变成为的数据类型list4.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {String[] arr = s.split("-");String ageString = arr[1];int age = Integer.parseInt(ageString);return age;}}).forEach(s -> System.out.println(s));list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));}
}

3. Stream流的终结方法

方法名称 说明
void forEach ( Consumer action ) 遍历
long count ( ) 统计
toArray ( ) 收集流中的数据,放到数组中
collect ( Collector collector ) 收集流中的数据,放到集合中
public class StreamTest02 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三", "李四", "王五", "赵六");// 遍历// Consumer的泛型:表示流中的数据类型// accept方法的形参s:依次表示流中的每一个数据//list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});list.stream().forEach(s -> System.out.println(s)); // 张三 李四 王五 赵六// 统计long count = list.stream().count();System.out.println(count); // 4// 收集数据放进数组Object[] arr1 = list.stream().toArray();System.out.println(Arrays.toString(arr1)); // [张三, 李四, 王五, 赵六]// 指定数据类型// Infunction的泛型:具体类型的数组// apply中形参:流中数据的个数,要跟数组长度一致// apply的返回值:具体类型的数组String[] arr2 = list.stream().toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});// toArray方法中的参数:只是创建一个指定类型的数组// toArray底层: 会此意得到流中的每一个数据,并把数据放到数组中// toArray的返回值:是一个装着流里面所有数据的数组System.out.println(Arrays.toString(arr2));// lambda表达式String[] arr3 = list.stream().toArray(value -> new String[value]);System.out.println(Arrays.toString(arr3));}
}

 collect方法:

public class StreamTest {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三-男-23", "李四-男-24", "王五-男-25", "赵六-女-27", "孙八-女-28");//收集到List集合当中//需求://将所有的男性收集起来List<String> newList = list.stream().filter(s-> "男".equals(s.split("-")[1])).collect(Collectors.toList());System.out.println(newList);  //[张三-男-23, 李四-男-24, 王五-男-25]//收集到Set集合当中Set<String> newSet = list.stream().filter(s-> "男".equals(s.split("-")[1])).collect(Collectors.toSet());System.out.println(newSet);//收集到Map集合当中//键: 姓名  值: 年龄//toMap://参数一表示键的生成规则  参数二表示值得生成规则//参数一:  //Function泛型一:表示流中每一个数据的类型 ;//        泛型二:表示Map集合中键的数据类型//方法apply 形参:一次表示流里面的每一个数据//        方法体:生成键的代码 //        返回值:已生成的键//参数二://Function泛型一:表示流中每一个数据的类型 ;//        泛型二:表示Map集合中值的数据类型//方法apply 形参:一次表示流里面的每一个数据//        方法体:生成值的代码 //        返回值:已生成的值Map<String, Integer> newMap = list.stream().filter(s-> "男".equals(s.split("-")[1])).collect(Collectors.toMap(new Function<String, String>() {@Overridepublic String apply(String s) {return s.split("-")[0];}}, new Function<String, Integer >() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split("-")[2]);}}));System.out.println(newMap);  //{李四=24, 张三=23, 王五=25}//lambda表达式Map<String, Integer> newMap1 = list.stream().filter(s-> "男".equals(s.split("-")[1])).collect(Collectors.toMap( s-> s.split("-")[0], s-> Integer.parseInt(s.split("-")[2])));System.out.println(newMap1);}
}

四、 练习

1.  数据过滤

需求:

定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10

过滤奇数,只留下偶数。
并将结果保存起来

public class StreamDemo {public static void main(String[] args) {// 1.定义一个集合ArrayList<Integer> list = new ArrayList<>();// 2.添加数据Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 3.过滤奇数,只留偶数// 进行判断,如果是偶数,返回trueList<Integer> list2 = list.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());System.out.println(list2); //[2, 4, 6, 8, 10]}
}

2.  数据操作 - 按年龄筛选

需求:
创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄

“zhangsan,23”
      “lisi,24"
      “wangwu,25”
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值

public class StreamDemo {public static void main(String[] args) {// 1.定义一个集合ArrayList<String> list = new ArrayList<>();//2.集合添加字符串list.add( "zhangsan,23");list.add("lisi,24");list.add("wangwu,25");//3.保留年龄大于24岁的人Map<String, Integer> map = list.stream().filter(s -> Integer.parseInt(s.split(",")[1]) >= 24).collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));System.out.println(map);  //{lisi=24, wangwu=25}}
}

3. 数据操作 - 演员信息要求筛选

现在有两个ArrayList集合,
第一个集合中:存储6名男演员的名字和年龄。第二个集合中:存储6名女演员的名字和年龄。姓名和年龄中间用逗号隔开。比如:张三,23
要求完成如下的操作:

  1. 男演员只要名字为3个字的前两人
  2. 女演员只要姓杨的,并且不要第一个
  3. 把过滤后的男演员姓名和女演员姓名合并到一起
  4. 将上一步的演员信息封装成Actor对象。
  5. 将所有的演员对象都保存到List集合中。

备注:演员类Actor,属性有:name,age

public class StreamDemo {public static void main(String[] args) {// 1.定义两个集合ArrayList<String> manList = new ArrayList<>();ArrayList<String> womenList = new ArrayList<>();// 2.添加数据Collections.addAll(manList, "蔡坤坤,24", "叶购成,23", "刘不甜,22", "吴签,24", "谷嘉,30", "肖梁梁,27");Collections.addAll(womenList, "赵小颖,35", "杨颖,36", "高元元,43", "张天天,31", "刘诗,35", "杨小幂,33");// 3. 男演员只要名字为3个字的前两个人Stream<String> stream1 = manList.stream().filter(s -> s.split(",")[0].length() == 3).limit(2);
//      .forEach(s -> System.out.println(s)); // 蔡坤坤,24  叶购成,23// 叶购成,23//4.女演员只要姓杨的 并且不要第一个Stream<String> stream2 = womenList.stream().filter(s -> s.split(",")[0].startsWith("杨")).skip(1);
//      .forEach(s -> System.out.println(s));  //杨小幂,33//5.把过滤的男演员和女演员信息合并在一起//演员信息封装进Actor对象//String -> Actor对象(类型转换)List<Actor> list = Stream.concat(stream1, stream2).map(s -> new Actor(s.split(",")[0],Integer.parseInt(s.split(",")[1]))).collect(Collectors.toList());System.out.println(list);}
}

JAVA—— Steam流相关推荐

  1. java Steam流的用法

    java Steam流的用法1 java Steam流的用法2 项目中的流用法不太懂,沾出来大家一路分享,有清楚地可以评论留言.

  2. 使用java Steam流进行逻辑分页(内存分页)

    物理分页与逻辑分页 物理分页 物理分页依赖的是某一物理实体,这个物理实体就是数据库,比如MySQL数据库提供了limit关键字,程序员只需要编写带有limit关键字的SQL语句,数据库返回的就是分页结 ...

  3. 记录Java Steam流的一些用法

    基础示例类: Use.java public class User {private String userId;private String userName;private Integer age ...

  4. java中steam流的使用

    (1)数组合并 : 原始合并 定义俩个集合合并为一个集合 例子: public class 测试 {/*** 把小王合道* list中* */public static void main(Strin ...

  5. Java中Steam流的用法及使用备忘

    文章目录 Java中Steam流的用法及使用备忘 一. 流的常用创建方法 1-1 使用Collection下的 stream() 和 parallelStream() 方法 1-2 使用Arrays ...

  6. Java Stream(流)的分类, 四大基本流的介绍

    上一篇文章已经介绍过什么是流, 以及流的基本概念 http://blog.csdn.net/nvd11/article/details/29917065 本文主要介绍java四大基本流的方法. 一, ...

  7. 可变参数和Steam流的基本使用

    1.可变参数 2.不可变集合 3. Steam流 3.1 对象流化 3.2 操作流的方法 3.3 收集方法 1.可变参数 内容是比较简单的,就介绍一下如何使用吧 public static void ...

  8. Java函数式编程教程(五):Java Steam API

    译:GentlemanTsao,2020-7-7 文章目录 Java Steam 定义 Steam 处理 获取Steam 终结操作和中间操作 中间操作 filter() map() flatMap() ...

  9. Java Stream流基础

    Java Stream流基础 何为Steam流? Stream 是对集合数组对象功能的增强,其专注于对集合数组对象进行各种非常便利.高效的聚合操作,或者大批量数据操作.通常我们需要多行代码才能完成的操 ...

最新文章

  1. JavaScript学习笔记(2)——JavaScript和DOM的关系
  2. 分析手机网站的优势思维结构图_写了100多篇原创文章,我常用的在线工具网站推荐给大家...
  3. IBMX3650M3服务器8硬盘升级16硬盘的配置方法
  4. 是什么动词_动词后面跟什么词?答案笑喷...
  5. 信用卡申请被拒原因分析
  6. Abp vNext 后台作业hangfire
  7. Linux之软连接和硬链接
  8. 来华30载,这些都是Oracle的神来之笔……
  9. 2021 ZUST,XCPC选拔赛
  10. 单模光纤和多模光纤的区别_一分钟了解光纤、单模光纤、多模光纤
  11. matlab log函数
  12. CCNet: Criss-Cross Attention for Semantic Segmentation论文解读
  13. 网易面试题,小易沉迷游戏
  14. 【Paper】法律科技方面论文汇总
  15. 阿里面试题:设计相关的系统对外提供商品实时价格获取功能
  16. 东大22春领导科学与决策X《领导科学与决策》在线平时作业2题目非答案
  17. @SpringBootTest与@RunWith注解的区别
  18. 向产品宣战——开发者眼中的Android UI Design
  19. Map接口的常见方法
  20. 定义一个复数类Complex

热门文章

  1. ProgressDialog总结
  2. 查询结果按照数量排序,并且将某条记录固定放到最后一行
  3. 二次元属性被稀释,B站还剩什么?(下篇)
  4. 直流浪涌保护器的选型指南方案
  5. PHP源码1001PHP源码,某区块链养殖系统平台PHP源码无加密完整版,带充值接口+完整会员系统 可封装APP可二开...
  6. 树莓派c语言pca9685,使用树莓派控制16路舵机驱动板(pca9685)
  7. 阿里云服务器Linex系统搭建Tomcat部署Web项目
  8. 如何下载安装oracle可视化工具PL/SQL Developer
  9. 怎样用css设置横向的滚动条,如何用CSS设置滚动条颜色?
  10. 二叉树层次遍历:队列