使用 Java 8 的 BiPredicate 和 Stream API 进行数据过滤和分组

news2025/1/9 14:50:37

在本文中,我们将学习如何使用 Java 8 的 BiPredicate 和 Stream API 来进行数据过滤和分组。我们将通过一个具体的例子来演示这一过程,例子中包含学生成绩的筛选和基于考试时间段的分组。

案例介绍

我们有两个实体类:StudentScoreExamTimePeriodStudentScore 代表学生的考试成绩,包含学生姓名、考试时间和分数;ExamTimePeriod 代表考试的时间段,包含开始时间、结束时间和考试轮次。

Maven依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.27</version>
        </dependency>

实体类定义

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 考试的时间段,包含开始时间、结束时间和考试轮次
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ExamTimePeriod {
    private String startTime;
    private String endTime;
    private String rounds;
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
 * 学生的考试成绩,包含学生姓名、考试时间和分数
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public  class StudentScore {
    private String studentName;
    private LocalDateTime scoreTime;
    private double score;

}

测试数据生成

 

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

public class BiPredicateDemo {
    public static void main(String[] args) {
        // 生成测试数据
        List<StudentScore> studentScores = Arrays.asList(
                new StudentScore("Alice", LocalDateTime.parse("2023-07-29T08:00:00"), 85.0),
                new StudentScore("Bob", LocalDateTime.parse("2023-07-29T18:00:00"), 90.0),
                new StudentScore("Charlie", LocalDateTime.parse("2023-07-29T12:00:00"), 95.0),
                new StudentScore("John", LocalDateTime.parse("2023-07-29T07:00:00"), 88.0),
                new StudentScore("David", LocalDateTime.parse("2023-07-29T20:00:00"), 80.0)
        );

        ExamTimePeriod morningTimePeriod = new ExamTimePeriod("06:00:00", "12:00:00", "晨考");
        ExamTimePeriod afternoonTimePeriod = new ExamTimePeriod("12:00:00", "18:00:00", "午考");
        ExamTimePeriod eveningTimePeriod = new ExamTimePeriod("18:00:00", "22:00:00", "晚考");
        List<ExamTimePeriod> examTimePeriodList = new ArrayList<>();
        examTimePeriodList.add(morningTimePeriod);
        examTimePeriodList.add(afternoonTimePeriod);
        examTimePeriodList.add(eveningTimePeriod);
        // 创建一个 BiPredicate 来过滤学生成绩,筛选出成绩高于85分的学生。
        filterScores(studentScores);
        System.out.println("-----------");
        // 按照考试时间段(早上、中午、晚上)进行分组。
        filterScoresByTimePeriod(studentScores, morningTimePeriod, afternoonTimePeriod, eveningTimePeriod);
        System.out.println("=============");
        // 过滤出成绩高于 minScore 且考试时间在指定时间段(examTimePeriod)内的学生成绩。
        List<StudentScore> studentScoresList1 = filterScoresWithMinScore(studentScores, 85.0, morningTimePeriod);
        System.out.println(studentScoresList1);
        // 过滤出所有成绩在指定范围(scoreRange)内且考试时间在指定时间段(examTimePeriod)内的学生列表。
        List<StudentScore> studentScoreList2 = filterScoresWithScoreRangeAndTimePeriod(studentScores, new Double[]{80.0, 95.0}, morningTimePeriod);
        System.out.println(studentScoreList2);
        System.out.println("*************");
        // 过滤出成绩在指定范围内的学生(例如,成绩在80到95之间),并根据考试时间段(早上、下午、晚上)进行分组。
        Map<String, List<StudentScore>> groupedScores = groupAndFilterScores(studentScores, examTimePeriodList);
        System.out.println(groupedScores);
    }
}

功能实现

创建一个 BiPredicate 来过滤学生成绩,筛选出成绩高于85分的学生。
    /**
     * 创建一个 BiPredicate 来过滤学生成绩,筛选出成绩高于85分的学生。
     *
     * @param studentScores 学生成绩列表
     */
    private static void filterScores(List<StudentScore> studentScores) {
        BiPredicate<StudentScore, Double> scoreFilter = (item, score) -> item.getScore() > score;
        List<StudentScore> collect = studentScores.stream().filter(item -> scoreFilter.test(item, 85.0))
                .collect(Collectors.toList());
        System.out.println(collect);
    }
使用 BiPredicate 过滤学生成绩,按照考试时间段(早上、中午、晚上)进行筛选。
 /**
     * 使用 BiPredicate 过滤学生成绩,按照考试时间段(早上、中午、晚上)进行筛选。
     *
     * @param studentScores 学生成绩列表
     * @param morningTimePeriod 早上考试时间段
     * @param afternoonTimePeriod 中午考试时间段
     * @param eveningTimePeriod 晚上考试时间段
     */
    private static void filterScoresByTimePeriod(List<StudentScore> studentScores, ExamTimePeriod morningTimePeriod,
                          ExamTimePeriod afternoonTimePeriod, ExamTimePeriod eveningTimePeriod) {
        // 使用 BiPredicate 进行数据过滤
        BiPredicate<StudentScore, ExamTimePeriod> timePeriodFilter = (item, config) -> {
            String scoreTime = item.getScoreTime().format(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
            return scoreTime.compareTo(config.getStartTime()) >= 0 && scoreTime.compareTo(config.getEndTime()) < 0;
        };

        List<StudentScore> morningScores = filterScores(studentScores, morningTimePeriod, timePeriodFilter);
        List<StudentScore> afternoonScores = filterScores(studentScores, afternoonTimePeriod, timePeriodFilter);
        List<StudentScore> eveningScores = filterScores(studentScores, eveningTimePeriod, timePeriodFilter);
        System.out.println("早上考试:" + morningScores);
        System.out.println("中午考试:" + afternoonScores);
        System.out.println("晚上考试:" + eveningScores);
    }
    /**
     * 过滤学生成绩,使用指定的时间段过滤器(BiPredicate)。
     *
     * @param studentScores 学生成绩列表
     * @param timePeriodConfig 时间段配置
     * @param filter 过滤器
     * @return 符合条件的学生成绩列表
     */
    private static List<StudentScore> filterScores(List<StudentScore> studentScores, ExamTimePeriod timePeriodConfig, BiPredicate<StudentScore, ExamTimePeriod> filter) {
        return studentScores.stream()
                .filter(item -> filter.test(item, timePeriodConfig))
                .collect(Collectors.toList());
    }
过滤成绩高于 minScore 且考试时间在指定时间段(examTimePeriod)内的学生成绩。
/**
     * 过滤成绩高于 minScore 且考试时间在指定时间段(examTimePeriod)内的学生成绩。
     *
     * @param studentScores 学生成绩列表
     * @param minScore 最低成绩
     * @param examTimePeriod 考试时间段
     * @return 符合条件的学生成绩列表
     */
    private static List<StudentScore> filterScoresWithMinScore(List<StudentScore> studentScores, double minScore,
                                        ExamTimePeriod examTimePeriod) {
        BiPredicate<StudentScore, Double> scoreFilter = (student, score) -> student.getScore() > score;
        BiPredicate<StudentScore, ExamTimePeriod> timePeriodFilter = (student, config) -> {
            String scoreTime = LocalDateTimeUtil.format(student.getScoreTime(), DatePattern.NORM_TIME_PATTERN);
            return scoreTime.compareTo(config.getStartTime()) >= 0 && scoreTime.compareTo(config.getEndTime()) < 0;
        };

        return studentScores.stream()
                .filter(student -> scoreFilter.test(student, minScore) && timePeriodFilter.test(student, examTimePeriod))
                .collect(Collectors.toList());
    }
过滤出所有成绩在指定范围(scoreRange)内且考试时间在指定时间段(examTimePeriod)内的学生列表。
/**
     * 过滤出所有成绩在指定范围(scoreRange)内且考试时间在指定时间段(examTimePeriod)内的学生列表。
     *
     * @param studentScores 学生成绩列表
     * @param scoreRange 成绩范围
     * @param examTimePeriod 考试时间段
     * @return 符合条件的学生成绩列表
     */
    private static List<StudentScore> filterScoresWithScoreRangeAndTimePeriod(List<StudentScore> studentScores, Double[] scoreRange,
                                                    ExamTimePeriod examTimePeriod) {
        BiPredicate<StudentScore, Double[]> scoreRangeFilter = (student, range) -> student.getScore() >= range[0] && student.getScore() <= range[1];
        BiPredicate<StudentScore, ExamTimePeriod> timePeriodFilter = (student, timePeriod) -> {
            String scoreTime = student.getScoreTime().format(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
            return scoreTime.compareTo(timePeriod.getStartTime()) >= 0 && scoreTime.compareTo(timePeriod.getEndTime()) < 0;
        };

        return studentScores.stream()
                .filter(student -> scoreRangeFilter.test(student, scoreRange) && timePeriodFilter.test(student, examTimePeriod))
                .collect(Collectors.toList());
    }
过滤出成绩在指定范围内的学生(例如,成绩在80到95之间),并根据考试时间段(早上、下午、晚上)进行分组。
/**
     * 过滤出成绩在指定范围内的学生(例如,成绩在80到95之间),
     * 并根据考试时间段(早上、下午、晚上)进行分组。
     *
     * @param studentScoreList 学生成绩列表
     * @param examTimePeriodList 考试时间段列表
     * @return 分组后的学生成绩映射
     */
    private static Map<String, List<StudentScore>> groupAndFilterScores(List<StudentScore> studentScoreList, List<ExamTimePeriod> examTimePeriodList) {
        // 成绩区间
        Double[] scoreRange = {80.0, 95.0};

        // 定义成绩范围过滤器
        BiPredicate<StudentScore, Double[]> scoreRangeFilter = (student, range) ->
                student.getScore() >= range[0] && student.getScore() <= range[1];

        // 定义考试时间段过滤器
        BiPredicate<StudentScore, ExamTimePeriod> timePeriodFilter = (student, period) -> {
            String scoreTime = student.getScoreTime().format(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
            return scoreTime.compareTo(period.getStartTime()) >= 0 && scoreTime.compareTo(period.getEndTime()) < 0;
        };

        // 使用 HashMap 分组
        Map<String, List<StudentScore>> groupedScores = new HashMap<>();
        for (ExamTimePeriod timePeriod : examTimePeriodList) {
            List<StudentScore> filteredScores = studentScoreList.stream()
                    .filter(student -> scoreRangeFilter.test(student, scoreRange)
                            && timePeriodFilter.test(student, timePeriod))
                    .collect(Collectors.toList());

            groupedScores.put(timePeriod.getRounds(), filteredScores);
        }
/*        // 使用 groupingBy 进行分组
        Map<String, List<StudentScore>> groupedScores =
                studentScoreList.stream().filter(student -> scoreRangeFilter.test(student, scoreRange))
                        .collect(Collectors.groupingBy(student -> {
                            for (ExamTimePeriod timePeriod : examTimePeriodList) {
                                String scoreTime = student.getScoreTime().format(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
                                if (scoreTime.compareTo(timePeriod.getStartTime()) >= 0 && scoreTime.compareTo(timePeriod.getEndTime()) < 0) {
                                    return timePeriod.getRounds();
                                }
                            }
                            return "非正常考试时间段";
                        }));*/
        return groupedScores;
    }

总结

通过本例,我们学习了如何使用 Java 8 的 BiPredicate 和 Stream API 进行复杂的过滤和分组操作。使用 BiPredicate 可以使代码更加清晰和灵活,非常适合用于需要多个条件进行筛选的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1969398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

满客宝智慧食堂系统 selectUserByOrgId 未授权访问漏洞复现

0x01 产品简介 满客宝智慧食堂系统由正奇晟业&#xff08;北京&#xff09;科技有限公司开发&#xff0c;旨在通过科技手段提升食堂的服务水平和就餐体验。该系统支持多种食堂就餐形式&#xff0c;如自选餐、自助餐、档口就餐、预订取餐等&#xff0c;满足不同场景下的餐饮需求…

从理论到实践网络编程模型:(BIO、NIO、AIO)同步与异步模型的原理与应用 (四)

我是写Java的就用Java及所需要的基础来写的本篇文章&#xff0c;其他语言的讲解和应用暂时也不会&#xff0c;欢迎大佬在评论区指导&#xff0c;给出其他语言的讲解分析与应用 Java数据传输字符流和字节流 java.io 是 Java 编程语言中的一个包&#xff0c;主要用于输入和输出&…

Linux 和 Unix 的关系

Linux 和 Unix 的关系 2.2.1unix 是怎么来的 2.2.2Linux 是怎么来的 GNU计划的另一个目的是构建自由的软件文化&#xff0c;以支持以无条件自由软件和开放源码程序这种文化理念为核心的一整套系统&#xff0c;来推动软件在世界范围内的普及及发展。其中包括支持点&#xff08;推…

java开发环境搭建基础之2----开发工具eclipse在windows的安装

一.背景 公司安排了带徒弟任务&#xff0c;写点基础的环境搭建这些吧。搭建基础开发环境&#xff0c;主要是jdk、eclipse、git、maven、mysql。后续再考虑编写jenkins、nexus、docker、1panel等CI/CD环境搭建。本次主要内容是eclipse的下载安装及运行。我的开发环境&#xff0c…

Linux内核(4)——Linux设备文件open函数从应用到内核全过程解析

学习并整理了下open等系统调用&#xff0c;从用户态如何调用到内核态的全过程。 1.Linux内核目录总览 2.Linux文件系统与设备驱动关系 这是在Linux设备驱动开发详解里找的两张图&#xff0c;内容很形象。 当用户程序通过系统调用陷入内核态时&#xff0c;会先经过VFS&#xf…

Hive3:表操作常用语句-内部表、外部表

一、内部表 1、基本介绍 &#xff08;CREATE TABLE table_name ......&#xff09; 未被external关键字修饰的即是内部表&#xff0c; 即普通表。 内部表又称管理表,内部表数据存储的位置由hive.metastore.warehouse.dir参数决定&#xff08;默认&#xff1a;/user/hive/ware…

多线程处理

1、使用两个线程完成两个文件的拷贝&#xff0c;分支线程1拷贝前一半&#xff0c;分支线程2拷贝后一半&#xff0c;主线程回收两个分支线程的资源 #include<myhead.h>struct Buf {int start;//起始位置int end;//结束位置const char *arr;//源文件const char *brr;//目标…

Spring-component-scan标签详解

<context:component-scan base-package"cn.ybzy.springtest"/> 首先&#xff0c;这标签是需要context的命名空间的。 base-package&#xff1a; 指定spring扫描注解的类所在的包。当需要扫描多个包的时候&#xff0c;可以使用逗号分隔。 如果只希望扫描特定…

Linux防火墙2

一、SNAT和DNAT SNAT&#xff1a;让内网机器可以访问外网服务器 DNAT: 让外网机器可以访问内网服务器 1.1、SNAT原理与应用 SNAT 应用环境 局域网主机共享单个公网IP地址接入Internet (私有IP不能在Internet中正常路由)&#xff0c;私转公 SNAT原理:源地址转换&#xff0c;…

水平直逼高级病理学家!清华团队提出AI基础模型ROAM,实现胶质瘤精准诊断

胶质瘤是一种源自脑内神经胶质细胞的肿瘤&#xff0c;占据所有原发性中枢神经系统肿瘤的 40&#xff05;~60&#xff05;&#xff0c;并以成年人最常见的颅内原发性肿瘤而闻名。胶质瘤的组织病理分类非常复杂&#xff0c;通常分为三种亚型&#xff1a;星形细胞瘤、少突胶质细胞…

使用go的tls库搭建客户端服务器加密通信

文章目录 使用OpenSSL生成证书Win系统安装openssl生成证书 非HTTP 直接tcp通信服务器代码客户端代码通信效果 使用OpenSSL生成证书 Win系统安装openssl 安装地址 https://slproweb.com/products/Win32OpenSSL.html设置环境变量 cmd命令检验 openssl version 生成证书 生成C…

2024.7.28 记录一次悲惨的笔试——作业帮NLP校招

小红的奇偶抽取 题目描述 题解 #include <iostream> #include<stack> using namespace std;int main() {long long n;stack <int> ji, ou;cin >> n;while (n) {int a n % 10;if (a % 2 0)ou.push(a);elseji.push(a);n n / 10;}long long jN 0, o…

Spring Cloud中怎么使用Resilience4j Retry对OpenFeign进行重试

在微服务架构中&#xff0c;服务之间的通信是非常频繁的。而使用OpenFeign可以极大简化微服务之间的HTTP通信。但在复杂的分布式系统中&#xff0c;服务之间的调用可能会因为网络问题、服务故障等原因而失败。因此&#xff0c;实现服务调用的重试机制显得尤为重要。Resilience4…

DDR3的使用(四)利用XILINX MIGIP核(native)读写DDR3—IP核信号分析

我们这一节继续结合仿真波形和逻辑分析仪测试波形来分析下MIGIP核的各个信号使用&#xff0c;这里主要说的是用户端的信号&#xff0c;这些信号直接与ip核进行交互&#xff0c;只有正确使用才能按我们的要求来读写数据。 1.我们先打开modelsim仿真软件&#xff0c;查看下examp…

机器学习笔记 - RAFT 光流简读

一、光流 光流是图像序列中像素的表观运动。为了估计光流,场景中物体的移动必须具有相应的亮度位移。这意味着一个图像中移动的红球在下一个图像中应该具有相同的亮度和颜色,这使我们能够确定它以像素为单位移动了多少。下图显示了光流示例,其中一系列图像捕获了逆时针旋转的…

使用 宝塔面板 部署 语料库php网站

【语料库网站】宝塔面板 在线部署全过程 代码仓库&#xff1a;https://github.com/talmudmaster/RedCorpus 网站介绍 语料库提供双语文本检索和分享功能。供英语、翻译相关专业的爱好者&#xff0c;学生和老师学习使用。 该网站是对BiCorpus开源项目的二次开发。 技术栈&am…

一文全面了解高性能计算平台是什么、怎么选型?高性能计算平台CHPC 都能做什么?

一. 概述 随着技术的发展和数据量的爆炸性增长&#xff0c;企业面临的挑战日益复杂&#xff0c;对计算能力的需求也在不断增加。这些问题的解决超出了传统计算方法的能力范围&#xff0c;高性能计算&#xff08;HPC&#xff09;正是为解决这类问题而生。 高性能计算&#xff…

怎么锁定Word文档格式,保护文档完整性

在日常工作和学习中&#xff0c;我们经常会使用Word文档来编辑和保存重要信息。然而&#xff0c;在文档被多人编辑或分享的过程中&#xff0c;格式的意外变动往往会给后续工作带来不必要的麻烦。为了确保文档的格式在编辑和分享过程中保持不变&#xff0c;我们可以采取一些措施…

2024还有跨境玩家没解锁代理IP+设备多开模式的强大吗?

大多数跨境电商平台对于IP地址、浏览器环境等限制严格。若同一台电脑在同一个跨境电商平台注册多个账号&#xff0c;很容易被官方封禁。如何在不触发官方封禁机制的前提下&#xff0c;安全高效地开展多账号运营策略&#xff0c;成为了众多跨境电商从业者亟待解决的问题。本文将…