一、引言

在上一篇文章中《这么简单,还不会使用java8 stream流的map()方法吗?》分享了使用stream的map()方法,不知道小伙伴还有印象吗,先来回顾下要点,map()方法是把一个流中的元素T转换为另外一个新流中的元素R,转换完成后两个流的元素个数不发生改变,具体怎么使用,请小伙伴移步上篇查看。在上篇文章中遗留了一个问题,本篇文章来解决它。先来看stream的另一个API--filter()方法。

二、概述

先来看下filter方法的定义,

该方法返回一个新流,这个新流中的元素要匹配给定的表达式。从方法的入参及出参可以看到返回的新流中的元素和元素流中的元素类型是一致的,和map()方法不同的是新流的元素个数要小于等于原始流的元素个数。

下面看下示意图,更清晰,

是不是很简单,下面看下具体的用法。

三、详述

以”找出一年级的所有学生的成绩“为例,来看下怎么使用filter()方法。同样初始化五个学生,

Data.java

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;
import java.util.ArrayList;
import java.util.List; /**
* @date 2022/11/30 22:43
*/
public class Data {
public static List<Student> initData(){
List<Student> students= new ArrayList<>(); Student s1=new Student();
s1.setName("王五");
s1.setSchoolClass("一年级");
s1.setChineseScore(100);
s1.setMathScore(100);
students.add(s1); Student s2=new Student();
s2.setName("李四");
s2.setSchoolClass("一年级");
s2.setChineseScore(100);
s2.setMathScore(100);
students.add(s2); Student s3=new Student();
s3.setName("李思");
s3.setSchoolClass("二年级");
s3.setChineseScore(100);
s3.setMathScore(100);
students.add(s3); Student s4=new Student();
s4.setName("王五");
s4.setSchoolClass("三年级");
s4.setChineseScore(100);
s4.setMathScore(100);
students.add(s4); Student s5=new Student();
s5.setName("赵三");
s5.setSchoolClass("一年级");
s5.setChineseScore(100);
s5.setMathScore(100);
students.add(s5);
return students;
}
}

Student.java类这里不在贴出,有兴趣的可以自己写,或参考上篇文章中的定义。直接看怎么实现。

3.1、找出一年级的所有学生成绩

要找出一年级的所有学生成绩,就要根据schoolClass进行过滤,看下使用filter()方法怎么写。

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;

import java.util.List;
import java.util.stream.Collectors; /**
* 测试filter()方法
* @date 2022/12/1 21:01
*/
public class TestFilter {
public static void main(String[] args) {
List<Student> students=Data.initData();
//使用filter对schoolClass进行过滤,满足条件的返回true,否则返回false,达到过滤的目的
List<Student> firstClass=students.stream().filter(student -> {
if("一年级".equals(student.getSchoolClass())){
return true;
}
return false;
}).collect(Collectors.toList());
//打印新的流
for (Student student:firstClass) {
System.out.println(student);
}
System.out.println("---------------------");
for (Student student:students) {
System.out.println(student);
}
}
}

使用filter()方法,该方法中的函数式接口,返回一个boolean类型的值,从而决定了该元素是否会写入到新流中。看下结果,

如果现在有这样一个需求,找出所有的一年级的学生,并给他们的数学成绩都减1分。要怎么办?

3.2、给一年级的所有同学的数学成绩减1分

我们可以在上面的基础上进行修改,完成此需求,

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;
import java.util.List;
import java.util.stream.Collectors;
/**
* 测试filter()方法
* @date 2022/12/1 21:01
*/
public class TestFilter {
public static void main(String[] args) {
List<Student> students=Data.initData();
//使用filter对schoolClass进行过滤,满足条件的返回true,否则返回false,达到过滤的目的
List<Student> firstClass=students.stream().filter(student -> {
if("一年级".equals(student.getSchoolClass())){
//所有一年级的学生,数学减1分
student.setMathScore(student.getMathScore()-1);
return true;
}
return false;
}).collect(Collectors.toList());
//打印新的流
for (Student student:firstClass) {
System.out.println(student);
}
System.out.println("---------------------");
for (Student student:students) {
System.out.println(student);
}
}
}

只需在上面的基础上增加一行代码即可,即符合条件的都减1分,看下打印结果。

从上面的解雇可以看到使用filter完成了该功能,但带来的一个副作用是原始数据也变了,主要是因为修改的是通过一个引用指向的对象。其实不太建议这样去写,因为filter()方法从字面意思就可以知道,它的作用就是过滤,最好不要参杂其他的逻辑,可以再加一个map()方法。

TestFilter2.java

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;

import java.util.List;
import java.util.stream.Collectors; /**
* 测试filter()方法
* @date 2022/12/1 21:01
*/
public class TestFilter2 {
public static void main(String[] args) {
List<Student> students=Data.initData();
//使用filter对schoolClass进行过滤,满足条件的返回true,否则返回false,达到过滤的目的
List<Student> firstClass=students.stream().filter(student -> {
if("一年级".equals(student.getSchoolClass())){
return true;
}
return false;
}).map(student -> {//map()方法
//设置数学成绩减1
student.setMathScore(student.getMathScore()-1);
return student;
}).collect(Collectors.toList());
//打印新的流
for (Student student:firstClass) {
System.out.println(student);
}
System.out.println("---------------------");
for (Student student:students) {
System.out.println(student);
}
}
}

上面在使用完filter后,由于是一个stream流,那么继续使用map()方法,对上一步过滤出的元素再对数学成绩减1操作,最后得到结果。通过一个示意图,

这样是不是比直接在fliter()中更加清晰。

四、总结

stream的filter()方法是要通过true/false来筛选元素,为true的会放到新流中,反之为false的不会放到新流中。

推荐阅读

这么简单,还不会使用java8 stream流的map()方法吗?

有不正之处,欢迎指正,谢谢!

感谢动动小手关注公众号【良工说技术】,更多精彩不容错过。

总算给女盆友讲明白了,如何使用stream流的filter()操作的更多相关文章

  1. 【ZZ】终于有人把云计算、大数据和人工智能讲明白了!

    终于有人把云计算.大数据和人工智能讲明白了! https://mp.weixin.qq.com/s/MqBP0xziJO-lPm23Bjjh9w 很不错的文章把几个概念讲明白了...图片拷不过来... ...

  2. 没讲明白的水题orz

    有一道解释程序的水题没给非计算机专业的同学讲明白orz,在这里再练一下.. 源代码完全没有缩进真是难以忍受.. p.s.懂递归就不用看了#include <stdio.h> int n = ...

  3. [CSP-S模拟测试]:小盆友的游戏(数学 or 找规律)

    题目传送门(内部题110) 输入格式 第一行一个整数$N$,表示小盆友的个数. 第二行$N$个整数$A_i$,如果$A_i=-1$表示$i$目前是自由身,否则$i$是$A_i$的跟班. 输出格式 一个 ...

  4. Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘

    Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘 package com.parllay.scala.dataset /** * Created by richard ...

  5. Scala 深入浅出实战经典 第39讲:ListBuffer、ArrayBuffer、Queue、Stack操作代码实战

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  6. 云计算分布式大数据Hadoop实战高手之路第八讲Hadoop图文训练课程:Hadoop文件系统的操作实战

    本讲通过实验的方式讲解Hadoop文件系统的操作. “云计算分布式大数据Hadoop实战高手之路”之完整发布目录 云计算分布式大数据实战技术Hadoop交流群:312494188,每天都会在群中发布云 ...

  7. 第三百六十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)基本的索引和文档CRUD操作、增、删、改、查

    第三百六十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)基本的索引和文档CRUD操作.增.删.改.查 elasticsearch(搜索引擎)基本的索引 ...

  8. MEF入门之不求甚解,但力求简单能讲明白(四)

    上一篇我们已经可以获取各种FileHandler的实例和对应的元数据.本篇,我们做一个稍微完整的文件管理器. 1.修改接口IFileHandler,传入文件名 namespace IPart { pu ...

  9. 终于有人把云计算、大数据和 AI 讲明白了

    最近学习hadoop以及生态,顺便看到了这篇文章,总结的很到位,转载下. 我今天要讲这三个话题,一个是云计算,一个大数据,一个人工智能,我为什么要讲这三个东西呢?因为这三个东西现在非常非常的火,它们之 ...

  10. 哪5种IO模型?什么是select/poll/epoll?同步异步阻塞非阻塞有啥区别?全在这讲明白了!

    系统中有哪5种IO模型?什么是 select/poll/epoll?同步异步阻塞非阻塞有啥区别? 本文地址http://yangjianyong.cn/?p=84转载无需经过作者本人授权 先解开第一个 ...

随机推荐

  1. 监控Redis集群--废弃,使用新教程

    prometheus监控redis需要用到redis_exporter. redis_exporter 项目地址:https://github.com/oliver006/redis_exporter ...

  2. POJ3280 Cheapest Palindrome (区间DP)

    dp[i][j]表示将字符串子区间[i,j]转化为回文字符串的最小成本. 1 #include<cstdio> 2 #include<algorithm> 3 #include ...

  3. 内存映射IO(MMIO)

    端口I/O 介绍: 一种I/O编址方式是端口映射I/O(port-mapped I/O), CPU使用专门的I/O指令对设备进行访问, 并把设备的地址称作端口号. 在执行其中的一条指令时,CPU使用地 ...

  4. mysql 过程和函数语法学习笔记

    CREATE DEFINER=`root`@`%` PROCEDURE `test`(`num` int) BEGIN /*定义变量*/ DECLARE sex TINYINT(2) DEFAULT ...

  5. 洛谷 P5607 [Ynoi2013] 无力回天 NOI2017

    人生第一道Ynoi,开心 Description https://www.luogu.com.cn/problem/P5607 Solution 拿到这个题,看了一下,发现询问要求最大异或和,怎么办? ...

  6. Hbase之API基本操作

    API之框架 private static Admin admin = null; private static Connection connection = null; private stati ...

  7. 齐博X1数据表之系统参数

    https://v.youku.com/v_show/id_XMzg0MTEzMzEyOA== 不会插入视频 直接发 优酷地址吧= =!

  8. Tesla-E380,4K eDP一键点屏神器问世

    eDP屏快速点亮,EDID回读, eDP屏调试 是否为点屏的准备工作感到烦躁: 1)查找LCD模组的数据手册(常常还未必能找着) 2)在上位机软件或者单片机程序里设置一大堆的LCD屏参,这个频率,那个 ...

  9. vue3渲染函数(h函数)的变化

    vue3 渲染函数(h函数)的更改 h函数的更改总结 1==>h 现在全局导入,而不是作为参数传递给渲染函数 2==>渲染函数参数更改为在有状态组件和函数组件之间更加一致 3==>v ...

  10. 二十一、Pod的存储之Secret

    Pod 的存储之Secret 一.Secret 存在意义 ​Secret 解决了密码.token.密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中.Secret 可以 ...