5.Stream流

5.1体验Stream流【理解】

  • 案例需求

    按照下面的要求完成集合的创建和遍历

    • 创建一个集合,存储多个字符串元素

    • 把集合中所有以"张"开头的元素存储到一个新的集合

    • 把"张"开头的集合中的长度为3的元素存储到一个新的集合

    • 遍历上一步得到的集合

  • 原始方式示例代码

package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap; /*
* 创建一个集合,存储多个字符串元素
"张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"
把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新的集合 遍历上一步得到的集合
*
* */
public class MyStream1 {
public static void main(String[] args) {
ArrayList<String> list1=new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
ArrayList<String> list2=new ArrayList<>();
//遍历list1把张开头的元素添加到list2中。
for (String s : list1) {
if (s.startsWith("张")) {
list2.add(s);
}
}
//遍历list2集合,把其中长度为3的元素,再添加到list3中,
ArrayList<String> list3=new ArrayList<>();
for (String s : list2) {
if (s.length() == 3) {
list3.add(s);
}
}
for (String s : list3) {
System.out.println(s);
}
//Stream流
list1.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length()==3)
.forEach(s -> System.out.println(s));
} }

Stream流的好处

  • 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印

  • Stream流把真正的函数式编程风格引入到Java中

  • 代码简洁

5.2Stream流的常见生成方式【应用】

  • Stream流的思想

  • Stream流的三类方法

    • 获取Stream流

      • 创建一条流水线,并把数据放到流水线上准备进行操作

    • 中间方法

      • 流水线上的操作

      • 一次操作完毕之后,还可以继续进行其他操作

    • 终结方法

      • 一个Stream流只能有一个终结方法

      • 是流水线上的最后一个操作

  • 生成Stream流的方式

    • Collection体系集合   单列集合

        使用默认方法stream()生成流, default Stream<E> stream()

    • Map体系集合   双列集合

        把Map转成Set集合,间接的生成流、  可以先通过keySet或者entrySet获取一个Set集合,在获取Stream流

    • 数组

        通过Arrays中的静态方法stream生成流

    • 同种数据类型的多个数据

        通过Stream接口的静态方法of(T... values)生成流

    • 1,2,3,4,5.......
    • "aaa","bbb","ccc"......
    • 使用Stream.of(T...values)生成流
package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Stream;
/*
* Stream流的获取
* 单列集合:集合对象.Stream();
* 双列集合:不能直接获取,需要间接获取
* 集合对象.keySet().stream();
* 集合对象.entrySet.stream();
*数组:Arrays.stream(数组名);
* 同种数据类型的多个数据:Stream.of(数据1,数据2,数据3.。。。。)
*
* */
public class MyStream2 {
public static void main(String[] args) {
//单列集合
//method1(); //双列集合
//method2(); //数组
//method3(); //同种数据类型的多个数据
method4();
} public static void method4() {
Stream.of(1,2,3,4,5,6,7,8).forEach(s-> System.out.println(s));
} public static void method3() {
int []arr={1,2,3,4,5};
Arrays.stream(arr).forEach(s-> System.out.println(s));
} public static void method2() {
HashMap<String,Integer> hm=new HashMap<>();
hm.put("zhangsan",23);
hm.put("lisi",24);
hm.put("wangwu",25);
hm.put("zhaoliu",26);
hm.put("qianqi",27);
//双列集合不能直接获取Streatm流
//KeySet
//先获取到所有的键
//再把这个Set集合中所有的键放到Stream流中
hm.keySet().stream().forEach(s -> System.out.println(s));
//entrySet
//先获取到所有的键值对对象
//再把这个Set集合中所有的键值对对象放到Stream流中
hm.entrySet().stream().forEach(s-> System.out.println(s));
} public static void method1() {
ArrayList<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
// Stream<String> stream = list.stream();
// stream.forEach(s -> System.out.println(s));
list.stream().forEach(s -> System.out.println(s));
} }

5.3Stream流中间操作方法【应用】

  • 概念

    中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作

  • 常见方法

    方法名 说明
    Stream<T> filter(Predicate predicate) 用于对流中的数据进行过滤
    Stream<T> limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据
    Stream<T> skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流
    static <T> Stream<T> concat(Stream a, Stream b) 合并a和b两个流为一个流
    Stream<T> distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流
  • filter代码演示

Stream<T> filter(Predicate predicate) 用于对流中的数据进行过滤

Predicate接口中的方法

boolean test(T t):对给定的参数进行判断,返回一个布尔值

package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate; public class MyStream3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
//filter方法获取流中的每一个数据
//而test方法中的s,就依次表示流中的每一个数据
//我们只要在test方法中对s进行判断就可以了,
//如果判断的结果为true,则当前的数据留下
//如果判断的结果为false,则当前的数据就不要
// list.stream().filter(
// new Predicate<String>() {
// @Override
// public boolean test(String s) {
// boolean result = s.startsWith("张");
// return result;
// }
// }
// ).forEach(s -> System.out.println(s));
//因为Predicate接口中只有一个抽象方法test
//所以我们能使用lambda表达式来简化
// list.stream().filter(
// (String s) -> {
// boolean result = s.startsWith("张");
// return result;
// }
// ).forEach(s -> System.out.println(s)); list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
}
}

limit&skip&concat&distinct代码演示  

package com.itheima.streamdemo;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream; public class MyStream4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
//Stream<T> limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据
//list.stream().limit(2).forEach(s -> System.out.println(s));
//Stream<T> skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流
//list.stream().skip(2).forEach(s -> System.out.println(s));
//static <T> Stream<T> concat(Stream a, Stream b) 合并a和b两个流为一个流
ArrayList<String> list2 = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤","谢广坤","谢广坤","谢广坤","谢广坤"));
// Stream<String> stream1 = list.stream();
// Stream<String> stream2 = list2.stream();
// Stream<String> stream3 = Stream.concat(stream1, stream2);
// stream3.forEach(s -> System.out.println(s));
//Stream.concat(list.stream(),list2.stream()).forEach(s -> System.out.println(s));
//Stream<T> distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流,依赖(hashCode和equals方法)
list.stream().distinct().forEach(s -> System.out.println(s)); }
}

5.4Stream流终结操作方法【应用】

  • 概念

    终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作

  • 常见方法

    方法名 说明
    void forEach(Consumer action)

    对此流的每个元素执行操作

    long count() 返回此流中的元素数
  • 代码演示

void forEach(Consumer action)

对此流的每个元素执行操作

Consumer接口中的方法              void accept(T t):对给定的参数执行此操作  

package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer; public class MyStream5 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
//void forEach(Consumer action)对此流的每个元素执行操作
//Consumer接口中的方法 void accept(T t):对给定的参数执行此操作  
//method1(list);
// long count()返回此流中的元素数
long count = list.stream().count();
System.out.println(count);
} public static void method1(ArrayList<String> list) {
//在forEach方法的底层 ,会循环获取到流中的每一个数据
//并循环调用accept方法,并把每一个数据传递给accept方法
//s就依次表示了流中的每一个数据
//所以,我们只要在accept方法中,写上处理的业务逻辑就可以了
list.stream().forEach(
new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
}
);
//lambda表达式的简化格式
//是因为Consumer接口中,只有一个accept方法
list.stream().forEach(s -> System.out.println(s));
}
}

需求:过滤元素并遍历集合

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

将集合中的奇数删除,只保留偶数

遍历集合得到2,4,6,8,10

package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.List; /*
*需求:过滤元素并遍历集合 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10 将集合中的奇数删除,只保留偶数 遍历集合得到2,4,6,8,10
*
*
* */
public class MyStream6 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
list.stream().filter(number -> number%2==0).forEach(number-> System.out.println(number));
System.out.println("==============");
for (Integer integer : list) {
System.out.println(integer);
}
}
}

  结论:在Stream流中无法直接修改集合,数组等数据源中的数据

5.5Stream流的收集操作【应用】

使用Stream流的方式操作完毕之后,我想把流中的数据保存起来,该怎么办

  • 概念

    对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中

  • 常用方法

    方法名 说明
    R collect(Collector collector) 把结果收集到集合中
  • 工具类Collectors提供了具体的收集方式

    方法名 说明
    public static <T> Collector toList() 把元素收集到List集合中
    public static <T> Collector toSet() 把元素收集到Set集合中
    public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中
  • 代码演示

  • 收集到list和set单列集合中
package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors; /*
*需求:过滤元素并遍历集合 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10 将集合中的奇数删除,只保留偶数 遍历集合得到2,4,6,8,10
*
*
* */
public class MyStream7 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
list.add(10);
list.add(10);
list.add(10);
list.add(10);
list.add(10);
//filter负责过滤数据的
//collect负责收集数据,
//获取流中剩余数据,但是他不负责创建容器,也不负责把数据添加到容器中
//Collectors.toList():在底层创建一个List集合,并把所有数据添加到List集合中
List<Integer> list1 = list.stream().filter(number -> number % 2 == 0)
.collect(Collectors.toList());
System.out.println(list1); Set<Integer> set = list.stream().filter(number -> number % 2 == 0)
.collect(Collectors.toSet());
System.out.println(set);
}
}

  收集到双列集合中

练习:

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

”zhangsan“,23

”lisi“,24

”wangwu“,25  

保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值

  

public static Collector toMap(Function keyMap,Function valueMapper):把元素收集到Map集合中  

package com.itheima.streamdemo;

import java.util.ArrayList;
import java.util.Map;
import java.util.stream.Collectors; /*
* 创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄 ”zhangsan“,23
”lisi“,24
”wangwu“,25  
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
*
* */
public class MyStream8 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("zhangsan,23");
list.add("lisi,24");
list.add("wangwu,25"); Map<String, Integer> map = list.stream().filter(
s -> {
String[] split = s.split(",");
int age = Integer.parseInt(split[1]);
return age >= 24;
}
//collection方法只能获取到流中剩余的每一个数据
//在底层不能创建容器,也不能把数据添加到容器当中 //Collectors.toMap 创建一个集合,并将数据添加到集合当中 //s依次表示流中的每一个数据 //第一个lambda表达式就是如何获取到map中的键
//第二个lambda表达式就是如何获取到map中的值
).collect(Collectors.toMap(
s -> s.split(",")[0],
s -> Integer.parseInt(s.split(",")[1])));
System.out.println(map);
}
}

5.6Stream流综合练习【应用】

  • 案例需求

    现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作

    • 男演员只要名字为3个字的前两人

    • 女演员只要姓杨的,并且不要第一个

    • 把过滤后的男演员姓名和女演员姓名合并到一起

    • 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据

    演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法

  • 代码实现

    演员类

package com.itheima.streamdemo;

public class Actor {
private String name; public Actor() {
} public Actor(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Actor{" +
"name='" + name + '\'' +
'}';
}
}

测试类  

package com.itheima.streamdemo;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.stream.Stream; /**
* 现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
* 1.男演员只要名字为3个字的前两人
* 2.女演员只要姓杨的,并且不要第一个
* 3.把过滤后的男演员姓名和女演员姓名合并到一起
* 4.把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
* 演员类Actor,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
*/
public class MyStream9 {
public static void main(String[] args) {
ArrayList<String> manList = new ArrayList<>();
manList.add("张国立");
manList.add("张晋");
manList.add("刘烨");
manList.add("郑伊健");
manList.add("徐峥");
manList.add("王宝强"); ArrayList<String> womanList = new ArrayList<>();
womanList.add("郑爽");
womanList.add("杨紫");
womanList.add("关晓彤");
womanList.add("张天爱");
womanList.add("杨幂");
womanList.add("赵丽颖");
//男演员只要名字为3个字的前两个人
Stream<String> stream1=manList.stream().filter(name -> name.length() == 3).limit(2);
//女演员只要姓杨的,并且不要第一个
Stream<String> stream2=womanList.stream().filter(name-> name.startsWith("杨")).skip(1); Stream.concat(stream1,stream2).forEach(name->{
Actor actor = new Actor(name);
System.out.println(actor);
});
} }

  

  

  

30.Stream流的更多相关文章

  1. 【重学Java】Stream流

    Stream流 体验Stream流[理解] 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合,存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把&q ...

  2. 乐字节-Java8新特性-接口默认方法之Stream流(下)

    接上一篇:<Java8新特性之stream>,下面继续接着讲Stream 5.流的中间操作 常见的流的中间操作,归为以下三大类:筛选和切片流操作.元素映射操作.元素排序操作: 操作 描述 ...

  3. 简洁方便的集合处理——Java 8 stream流

    背景 java 8已经发行好几年了,前段时间java 12也已经问世,但平时的工作中,很多项目的环境还停留在java1.7中.而且java8的很多新特性都是革命性的,比如各种集合的优化.lambda表 ...

  4. Java8新特性 Stream流式思想(一)

    遍历及过滤集合中的元素使用传统方式遍历及过滤集合中的元素package cn.com.zq.demo01.Stream.test01.Stream; import java.util.ArrayLis ...

  5. Java8新特性 Stream流式思想(三)

    Stream接口中的常用方法 forEach()方法package cn.com.cqucc.demo02.StreamMethods.Test02.StreamMethods; import jav ...

  6. 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)

    方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...

  7. 再来看看Java的新特性——Stream流

    半年前开始试着使用Java的新特性,给我印象最深的就是Stream流和Optional.其中Stream提高了看法效率,让代码看起来十分清爽. 为什么要使用流? 摘要中已经说明了,为了提高开发效率.流 ...

  8. 详解 stream流

    在本人之前的博文中,我们学习了 I/O流.NIO流的相关概念. 那么,在JDK8的更新内容中,提出了一个新的流 -- stream流 那么,现在,本人就来讲解下这个流: 目录 stream流 常用AP ...

  9. 第十章 函数式接口&Stream流

    10.1.函数式接口 10.1.1.概述 有且仅有一个抽象方法的接口,并且可以通过在类上标注@FunctionalInterface注解进行检测,建议自定义的函数式接口都加上这个注解 10.1.2.函 ...

随机推荐

  1. Java之继承和抽象类

    继承 继承的实现 继承通过extends实现 格式:class 子类 extends 父类 { } 举例:class Dog extends Animal { }   继承带来的好处 继承可以让类与类 ...

  2. 图解 | 原来这就是 IO 多路复用

    为了讲多路复用,当然还是要跟风,采用鞭尸的思路,先讲讲传统的网络 IO 的弊端,用拉踩的方式捧起多路复用 IO 的优势. 为了方便理解,以下所有代码都是伪代码,知道其表达的意思即可. Let's go ...

  3. 思维导图趋势大分析(MindMaster与百度脑图)

    思维导图现在可以说是大流行期间,涉及学习.工作.生活方方面面的内容. 一.什么是思维导图 思维导图的英文名称是The Mind Map,也叫做心智导图,脑图,心智地图,脑力激荡图等.思维导图应用图文兼 ...

  4. CentOS7 搭建 K8S 环境

    前期准备 环境规划 K8S 与Docker兼容问题 k8s v1.18.0 => Docker v18.x k8s v1.19.0 => Docker v19.x 软件 版本 Linux操 ...

  5. 全面了解Vue3的 ref 和相关函数和计算属性

    基础类型的响应性 -- ref 在vue3里面,我们可以通过 reactive 来实现引用类型的响应性,那么基础类型的响应性如何来实现呢? 可能你会想到这样来实现: const count = rea ...

  6. 案例分析作业——VS和VS Code

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 案例分析作业 我在这个课程的目标是 认真完成课程要求并提高相应能力 这个作业在哪个具体方面帮助我实现目标 学 ...

  7. SpringBoot(九篇)

    (一) SpringBootCLI安装 (二)SpringBoot开发第一个应用 (三)SpringBoot pom.xml配置文件详解 (四)SpringBoot起步依赖Starters详解 (五) ...

  8. 「Spring Boot 2.4 新特性」一键构建Docker镜像

    背景 在我们开发过程中为了支持 Docker 容器化,一般使用 Maven 编译打包然后生成镜像,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便.docker-maven-plugi ...

  9. CountDownLatch与CyclicBarrier的基本使用

    1 概述 CountDownLatch以及CyclicBarrier都是Java里面的同步工具之一,本文介绍了两者的基本原理以及基本使用方法. 2 CountDownLatch CountDownLa ...

  10. 抛弃vuex ,拥抱ts,手撸泛型Store<T>!

    前段时间学习了下vue3 和ts ,就尝试下做了个项目,结果发现vuex和ts几乎无法结合,越写越别扭,开始怀疑用ts就是自己给自己挖坑,然后加了几个vue相关的群,去抱怨了几句,得到大佬指点:你可以 ...