Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅

Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅

上周加完班打车回家,师傅问我:”这么晚才下班,程序员很辛苦吧?“

我说:”还好,就今天比较晚。“

师傅笑了笑没说话,但我心里苦啊。

事情是这样的。我们系统里有个报表模块,要从各种数据源捞数据,然后做转换、过滤、分组、汇总。光是DTO转VO,一天就得写七八次。

简单for循环

代码大概是这样:

List<User> users = userService.findAll();List<UserVO> result =newArrayList<>();for(User user : users){if(user.isActive()&& user.getAge()>18){UserVO vo =newUserVO(); vo.setName(user.getName()); vo.setAge(user.getAge());// 还有七八个字段要set... result.add(vo);}}

代码其实没毛病,就是不太好看。

于是用到了 Java8 的 Stream。

Stream 写法

List<UserVO> result = users.stream().filter(user -> user.isActive()&& user.getAge()>18).map(user ->{UserVO vo =newUserVO();BeanUtils.copyProperties(user, vo);return vo;}).collect(Collectors.toList());

看起来好多了,对吧?但这只是最简单的场景。

举例

假设有这样一个需求:

从员工列表里,按部门分组,计算每个部门的平均薪资,找出平均薪资大于5000的部门,按平均薪资从高到低排序,取前三名。

数据类长这样:

@Data@AllArgsConstructorclassEmployee{String name;String dept;double salary;}

Stream实现:

List<Employee> employees =Arrays.asList(newEmployee("张三","技术部",12000),newEmployee("李四","技术部",9000),newEmployee("王五","市场部",6000),newEmployee("赵六","市场部",4000),newEmployee("钱七","人事部",3000),newEmployee("孙八","人事部",8000));List<String> topDepts = employees.stream().collect(Collectors.groupingBy(Employee::getDept,Collectors.averagingDouble(Employee::getSalary))).entrySet().stream().filter(e -> e.getValue()>5000).sorted(Map.Entry.<String,Double>comparingByValue().reversed()).limit(3).map(Map.Entry::getKey).collect(Collectors.toList());

这里就有几个让人不舒服的地方:

  1. groupingBy,再对entrySet()流式处理,绕了一圈。
  2. 排序那段泛型推导,必须写Map.Entry.<String, Double>comparingByValue(),看着就累。
  3. 如果后续还要加条件(比如再关联另一张表),这个链会越来越臃肿。

这种代码在数据量不大、步骤少的时候没问题,可一旦要做转换、聚合等操作时,Stream 可读性会下降。


换JDFrame来写,画风突变

先加依赖(Maven):

<dependency><groupId>io.github.davidfantasy</groupId><artifactId>jdframe</artifactId><version>最新版本</version></dependency>

然后用它重写上面的逻辑:

DataFrame<Employee> df =JDFrame.create(employees);List<String> topDepts = df.groupBy("dept").avg("salary").as("avgSalary").filter(row -> row.getDouble("avgSalary")>5000).sortDesc("avgSalary").select("dept").head(3).toList(row -> row.getString("dept"));

是不是清晰的像写 SQL 一样?

  • groupBy("dept") → 按部门分组
  • avg("salary") → 计算薪资平均值
  • filter(...) → 过滤平均薪资>5000
  • sortDesc(...) → 降序排序
  • select("dept") → 只取部门列
  • head(3) → 取前三条

每一步都对应自然语言的一个动作,没有中间集合,没有泛型推导,没有流套流


JDFrame到底是什么?

简单说,JDFrame 是一个把集合数据当成表格来操作的工具。

对比 Stream:

  • Stream:一条一条遍历,一个个对象处理。
  • JDFrame:而 JDFrame 换了一种思路,它把你的 List<Employee> 看成一张表,适合多步骤数据清洗、报表统计、类SQL查询。

上手JDFrame,三步就够了

1. 创建DataFrame

最常见的是从List创建:

DataFrame<Employee> df =JDFrame.create(employees);

也可以从CSV文件、数据库ResultSet、二维数组等创建。

2. 日常操作——像玩Excel一样玩数据

筛选行(类似SQL的WHERE):

df.filter(row -> row.getInt("age")>30); df.filterEq("dept","技术部");// 等于某个值 df.filterIn("status",Arrays.asList(1,2,3));// in查询

选择列(类似SQL的SELECT):

df.select("name","salary"); df.drop("age");// 删除某列

新增/修改列

df.withColumn("annualSalary", row -> row.getDouble("salary")*12);

排序

df.sortAsc("age"); df.sortDesc("salary"); df.sort("dept",true,"age",false);// 多列排序:dept升序,age降序

分组聚合——这是JDFrame最爽的地方:

df.groupBy("dept").count().as("count").sum("salary").as("total").avg("salary").as("avg").max("age").as("maxAge").toList();

所有聚合函数都可以链式调用,结果就是一张新的DataFrame,不用像Stream那样先groupingBy,再处理Entry

3. 两个表格之间的连接(Join)

这是Stream最难搞的场景,但JDFrame几行搞定:

DataFrame<Employee> empDF =JDFrame.create(employees);DataFrame<Dept> deptDF =JDFrame.create(depts);DataFrame<?> joined = empDF.innerJoin(deptDF,"deptId","id").select("emp.name","dept.deptName","emp.salary");

innerJoinleftJoinrightJoinfullJoin都有,连接条件支持单字段或多字段组合。


哪些地方特别适合用JDFrame?

1. 报表导出/数据统计

比如从数据库查了几万条订单记录,要在内存中按地区、品类、时间段做多层聚合,最后生成Excel。

Stream写出来基本是个屎山,而JDFrame的链式分组聚合非常时候这种场景。

2. 数据清洗/ETL

从文件读入原始数据,需要去重、转换格式、填充默认值、过滤脏数据……JDFrame的withColumnfilterdropDuplicates一套下来,逻辑非常直观。

3. 接口数据组装

现在微服务流行,经常要从A服务查一批用户,从B服务查他们的订单,然后在内存里把两个列表关联起来,再按某种规则排序分页。

以前可能要自己维护Map<userId, List>,现在一个leftJoin搞定。


不是所有地方都适用

性能

JDFrame内部还是基于Stream+内存操作,大数据量(百万级以上)不如数据库直接聚合,适合中等规模数据。

学习成本

习惯了Stream的小伙伴刚接触列式思维,可能需要半天适应,不过一旦上手就回不去了。

生态

毕竟小众,和Spring、MyBatis没有官方集成,需要自己粘合。但这反而是优点——小巧,无侵入


写在最后

Stream 当然是个好东西,简单的过滤映射依然是它的主场。

但当我们遇到多步骤、表关联、类SQL聚合的场景时,可以尝试下 JDFrame

从设计思想上看,Stream 是面向对象 + 函数式组合的思路,而 JDFrame 更偏向列式数据模型。

一个是操作对象流,一个是操作表结构。

JDFrame 的价值,不是取代 Stream,而是补充。

本文首发于公众号:程序员大华,专注前端、Java开发,AI应用和工具的分享。关注我,少走弯路,一起进步!

Read more

【MySQL#5】 事务的概念及ACID属性和使用

【MySQL#5】 事务的概念及ACID属性和使用

📃个人主页:island1314 ⛺️ 欢迎关注:👍点赞 👂🏽留言 😍收藏 💞 💞 💞 * 生活总是不会一帆风顺,前进的道路也不会永远一马平川,如何面对挫折影响人生走向 – 《人民日报》 🔥 目录 * 一、什么是事务 * 二、事务的属性及使用 * 2.1 事务的 ACID 属性 * 2.2 为什么存在事务 * 2.3 事务的版本支持 * 2.4 事务的提交方式 * 2.5 事务的常见操作方式 一、什么是事务 * 定义:由一条或者多条 sql 语句构成的 sql 集合体,这个集合体合在一起共同要完成某种任务。MySQL通过多线程实现存储工作,因此在并发访问场景中,事务确保了数据操作的一致性和可靠性。 事务还规定 不同的客户端看到的数据是不相同的 * 事务就是要做的或所做的事情,主要用于 处理操作量大,复杂度高的数据

By Ne0inhk
Flutter 组件 whitecodel_auto_link 适配鸿蒙 HarmonyOS 实战:交互式文本探针,构建信息流自动链接识别与极速预览架构

Flutter 组件 whitecodel_auto_link 适配鸿蒙 HarmonyOS 实战:交互式文本探针,构建信息流自动链接识别与极速预览架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 whitecodel_auto_link 适配鸿蒙 HarmonyOS 实战:交互式文本探针,构建信息流自动链接识别与极速预览架构 前言 在鸿蒙(OpenHarmony)生态迈向深度社交、企业办公及即时通讯全场景覆盖的背景下,如何将枯燥的长文本转化为具备可交互能力的“信息枢纽”,已成为提升用户操作效率的关键。在鸿蒙设备这类强调分布式协同与智慧感知的移动终端上,如果应用仅能显示纯文本,而无法识别其中的网址(URL)、邮箱(Email)或电话(Phone),用户就必须通过复杂的“长按、复制、切换应用、粘贴”链路来处理信息,这极大地割裂了鸿蒙系统的流转体验。 我们需要一种能够自动扫描文本特征、支持多维热点识别且具备高性能渲染能力的富文本处理引擎。 whitecodel_auto_link 为 Flutter 开发者引入了极其简便的长文本自动链接方案。它通过内置的高精度正则匹配矩阵,自动将文本中的特定识别域转化为可点击的高亮区域。在适配到鸿蒙

By Ne0inhk
Spring Boot 后端分层开发实战:从 MVC 到三层架构详解

Spring Boot 后端分层开发实战:从 MVC 到三层架构详解

应用分层 通过上面的练习,我们学习了 Spring MVC 简单功能的开发,但是我们也发现了一些问题。目前我们程序的代码有点 “杂乱”,然而当前只是 “一点点功能” 的开发。如果我们把整个项目功能完成呢?代码会更加的 “杂乱无章”(文件乱,代码内容乱)。 也基于此,咱们接下来学习应用分层。类似公司的组织架构:公司初创阶段,一个人身兼数职,既做财务,又做人事,还有行政。随着公司的逐渐壮大,会把岗位进行细分,划分为财务部门,人事部门,行政部门等。各个部门内部还会再进行细分。 项目开发也是类似,最开始功能简单时,我们前后端放在一起开发,随着项目功能的复杂,我们分为前端和后端不同的团队,甚至更细粒度的团队。后端开发也会根据功能再进行细分。MVC 就是其中的一种拆分方式。但是随着后端人员不再涉及前端,后端开发又有了新的分层方式。 4.1 介绍 阿里开发手册中,关于工程结构部分,定义了常见工程的应用分层结构: 那么什么是应用分层呢?应用分层是一种软件开发设计思想,

By Ne0inhk

大模型实习模拟面试面经:同花顺金融大模型算法一面深度复盘(RAG、LoRA、强化学习、Agent 架构全解析)

大模型实习模拟面试面经:同花顺金融大模型算法一面深度复盘(RAG、LoRA、强化学习、Agent 架构全解析) 关键词:大模型面试|RAG 重排序|LoRA 参数优化|GRPO 训练异常处理|Agentic RL|金融 Agent 开发|AI for SE 前言:为什么这场面试值得复盘? 2026 年,大模型技术已从“学术热点”全面转向“工业落地”,尤其在金融、医疗、法律等高价值垂直领域,智能 Agent 正成为企业核心竞争力的关键载体。作为国内领先的金融科技公司,同花顺近年来大力投入金融大模型与智能投研 Agent 的研发,其算法岗面试自然聚焦于工程实现能力 + 领域理解深度 + 技术前沿敏感度三大维度。 本文基于真实模拟面试场景,完整还原一场面向大模型算法实习生岗位的一轮技术面全过程。面试官围绕 RAG 重排序机制、LoRA

By Ne0inhk