【JAVA进阶篇教学】第二十篇:如何高效处理List集合数据及明细数据

news2025/1/4 15:00:34

博主打算从0-1讲解下java进阶篇教学,今天教学第二十篇:如何高效处理List集合数据及明细数据。

Java 8 Stream API 助力高效处理集合数据(订单明细查询优化案例)

目录

一、前言 

二、问题回顾

三、优化思路与 Stream API 的运用

四、总结


一、前言 

目前采用的是jdk8中stream流来处理,以及一些效率高的方法来处理集合及明细数据。

二、问题回顾

我们有一个 List<Order> 类型的集合,其中 Order 类包含 orderId 字段,同时存在对应的订单明细表,由 OrderDetail 类表示明细信息。
常规的做法往往是这样去获取每个订单的明细数据:

List<Order> orderList = getOrderListFromSomewhere(); // 假设从某个地方获取到订单列表
for (Order order : orderList) {
    String orderId = order.getOrderId();
    OrderDetail detail = findOrderDetailByOrderId(orderId); // 每次循环都依据订单ID去数据库查询明细,频繁操作数据库
    // 后续对detail进行相应处理,比如关联到订单对象等
}

这种方式随着订单数量增多,频繁的数据库连接和查询操作会严重影响性能,所以我们需要进行优化。 

三、优化思路与 Stream API 的运用

利用 Java 8 的 Stream API,我们可以按如下优化思路进行操作:

  • 首先,从 List<Order> 集合中通过 Stream 的 map 操作提取出所有的 orderId,并收集为一个 List<String>。
  • 接着,使用提取出的 orderId 集合,一次性去数据库查询出所有对应的订单明细数据,避免多次单个查询。
  • 最后,把查询到的订单明细数据通过 Stream 的 collect 方法转变成以 orderId 为键,OrderDetail 对象为值的 Map<String, OrderDetail>,方便后续依据订单 orderId 快速获取对应明细。

以下是具体的代码实现,同样假设 Order 和 OrderDetail 类具有如下简单结构(实际项目中可根据真实业务需求扩展相应属性和方法):

class Order {
    private String orderId;
    // 其他订单相关字段及对应的getter、setter方法

    public String getOrderId() {
        return orderId;
    }
}

class OrderDetail {
    private String orderId;
    // 明细相关的各种字段及对应的getter、setter方法

    public String getOrderId() {
        return orderId;
    }
}

下面是运用 Stream API 优化后的完整代码:

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class OrderDataProcessingWithStream {

    public static void main(String[] args) {
        // 模拟获取订单列表
        List<Order> orderList = getOrderListFromSomewhere();
        // 提取orderId集合
        List<String> orderIdList = orderList.stream()
               .map(Order::getOrderId)
               .collect(Collectors.toList());
        // 一次性查询出所有订单明细数据
        List<OrderDetail> orderDetailList = findAllOrderDetails(orderIdList);
        // 将明细数据转成Map方便后续查找
        Map<String, OrderDetail> orderDetailMap = orderDetailList.stream()
               .collect(Collectors.toMap(OrderDetail::getOrderId, detail -> detail));

        // 现在可以方便地根据订单ID获取对应的明细数据了
        orderList.forEach(order -> {
            String orderId = order.getOrderId();
            OrderDetail detail = orderDetailMap.get(orderId);
            // 在这里可以进行后续的业务处理,比如将明细数据设置到订单对象等
            order.setOrderDetail(detail);
        });
    }

    // 模拟从某个地方获取订单列表,这里简单返回一个示例列表
    private static List<Order> getOrderListFromSomewhere() {
        // 创建示例订单列表,实际中可能从数据库、缓存等地方获取
        return List.of(
                new Order() {{
                    setOrderId("001");
                }},
                new Order() {{
                    setOrderId("002");
                }}
        );
    }

    // 模拟根据订单ID列表一次性查询出所有订单明细数据(实际中这里会涉及数据库操作)
    private static List<OrderDetail> findAllOrderDetails(List<String> orderIdList) {
        // 假设根据每个orderId去数据库查询并构建对应的OrderDetail对象添加到列表中
        return orderIdList.stream().map(orderId -> {
            OrderDetail detail = new OrderDetail();
            detail.setOrderId(orderId);
            // 模拟设置其他明细数据
            return detail;
        }).collect(Collectors.toList());
    }
}

在上述代码中:

  • 提取 orderId 集合部分:

通过 orderList.stream() 将订单列表转换为流,然后使用 map(Order::getOrderId) 操作,从每个 Order 对象中提取 orderId,最后通过 collect(Collectors.toList()) 将提取出来的 orderId 收集成一个 List<String>。这一步充分利用了 Stream API 简洁且函数式的风格来实现数据转换。

  • 将明细数据转成 Map 部分:

针对查询到的 orderDetailList,再次使用流操作 orderDetailList.stream(),接着通过 collect(Collectors.toMap(OrderDetail::getOrderId, detail -> detail)) 把明细列表转变成以 orderId 为键、OrderDetail 对象为值的 Map。这里 Collectors.toMap 方法的第一个参数指定了作为键的属性提取方式(即通过 OrderDetail::getOrderId 获取 orderId),第二个参数就是简单地返回明细对象本身,表示值的映射方式。

通过这样运用 Stream API 的优化方式,代码更加简洁易读,同时有效减少了数据库操作次数,尤其在处理大量订单数据时,能够显著提升程序性能,让数据处理变得更加高效和优雅。

四、总结

如果按照普通的思路做for循环去查找明细信息,假如List<Order>list 中有20条数据,那么你for循环部分就需要访问数据库20次,大大增加了io消耗,如果有更复杂的处理,那么程序就会很慢。

优化后,你只需要访问一次数据库,一次性查出所有数据,然后再内存中操作即可。

点个关注,不会迷路!

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

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

相关文章

Linux的介绍及虚拟机centOS系统的下载与应用

1、什么是Linux Linux 是一种类 Unix 操作系统&#xff0c;它的内核&#xff08;Kernel&#xff09;由 Linus Torvalds 于 1991 年首次发布。作为一个开源、免费的操作系统&#xff0c;Linux 被广泛用于服务器、桌面计算机、嵌入式设备、移动设备等各种场景。 1、操作系统 操…

ORACLE数据库直接取出数据库字段JSON串中的 VALUE内容

字段内容类似这种&#xff1a; 如果是12c以上版本可以使用 SELECT JSON_VALUE(MEMO, $.supplyExercisePrice) AS supplyExercisePrice FROM your_table;如果是11g版本可以使用 SELECT REGEXP_SUBSTR(MEMO, "supplyExercisePrice":"([^"])", 1, 1, …

业务分组:流量隔离

RPC中常用的保护手段“熔断限流”&#xff0c;熔断是调用方为了避免在调用过程中&#xff0c;服务提供方出现问题的时候&#xff0c;自身资源被耗尽的一种保护行为&#xff1b;而限流则是服务提供方为防止自己被突发流量打垮的一种保护行为。虽然这两种手段作用的对象不同&…

数据结构——排序算法第二幕(交换排序:冒泡排序、快速排序(三种版本) 归并排序:归并排序(分治))超详细!!!!

文章目录 前言一、交换排序1.1 冒泡排序1.2 快速排序1.2.1 hoare版本 快排1.2.2 挖坑法 快排1.2.3 lomuto前后指针 快排 二、归并排序总结 前言 继上篇学习了排序的前面两个部分:直接插入排序和选择排序 今天我们来学习排序中常用的交换排序以及非常稳定的归并排序 快排可是有多…

【JavaEE初阶 — 网络编程】Socket 套接字 & UDP数据报套接字编程

1. Socket套接字 1.1 概念 Socket 套接字&#xff0c;是由系统提供用于网络通信的技术&#xff0c;是基于TCP / IP协议的网络通信的基本操作单元。基于 Socket 套接字的网络程序开发就是网络编程。 1.2 分类 Socket套接字主要针对传输层协议划分为如下三类&#x…

熔断限流:业务实现自我保护

服务端-限流 服务端主要是通过限流来进行自我保护&#xff0c;实现限流时要考虑到应用和IP级别&#xff0c;方便在服务治理的时候&#xff0c;对部分访问量特别大的应用进行合理的限流&#xff1b;服务端的限流阈值配置都是作用于单机的&#xff0c;而在有些场景下&#xff0c…

linux系统误操作,设置nofile值超过限制,导致无法登录,permission denied

1.问题描述&#xff08;虚拟机复现&#xff09; 在k8s集群运行某些服务时&#xff0c;对文件描述符要求比较大&#xff0c;在提高这个值前未查询这个值的限制&#xff0c;最后设置了一个超过限制的值导致登录被拒绝 [roottest4 ~]# tail -3 /etc/security/limits.conf * sof…

从零开始配置Qt+VsCode环境

从零开始配置QtVsCode环境 文章目录 从零开始配置QtVsCode环境写在前面扩展安装及配置Qt Configure配置 VsCode创建Qt工程VsCodeQMakeMinGwVsCodeQMakeMsvcVsCodeCMakeMinGwVsCodeCMakeMsvcQtCreatorQMakeMinGw->VsCodeQtCreatorQMakeMsvc->VsCodeQtCreatorCMakeMinGw-&g…

如何借助AI生成PPT,让创作轻松又高效

PPT是现代职场中不可或缺的表达工具&#xff0c;但同时也可能是令人抓狂的时间杀手。几页幻灯片的制作&#xff0c;常常需要花费数小时调整字体、配色与排版。AI的飞速发展为我们带来了革新——AI生成PPT的技术不仅让制作流程大大简化&#xff0c;还重新定义了效率与创意的关系…

【Linux】Make/Makefile

这个3/4行的语法和1/2行是一样的。也是依赖关系和依赖方法。 make命令扫描makefile文件时&#xff0c;从上向下扫描&#xff0c;默认形成一个目标文件。 指定make clean的时候才回去执行对应的清除。 为什么要给我们的clean.PHONY:clean声明它是伪目标呢&#xff1f; PHONY类…

HarmonyOS:@Provide装饰器和@Consume装饰器:与后代组件双向同步

一、前言 Provide和Consume&#xff0c;应用于与后代组件的双向数据同步&#xff0c;应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递&#xff0c;Provide和Consume摆脱参数传递机制的束缚&#xff0c;实现跨层级传递。 其中Provi…

如何做好一份技术文档?

打造出色技术文档的艺术 在当今技术驱动的世界中&#xff0c;技术文档扮演着至关重要的角色。它不仅是工程师和开发人员之间交流的桥梁&#xff0c;更是产品和技术成功的隐形推手。一份优秀的技术文档宛如一张精准的航海图&#xff0c;能够引导读者穿越技术的迷雾&#xff0c;…

泰山众筹怎样吸引用户参与

泰山众筹项目要吸引用户参与&#xff0c;需要采取一系列策略来增强项目的吸引力、提高用户信任度&#xff0c;并激发用户的参与热情。以下是一些建议&#xff1a; 1. 明确项目价值与愿景 展示独特性&#xff1a;明确泰山众筹项目的独特卖点&#xff0c;如创新性、社会影响力或…

抓包之验证content-length响应头的作用

写在前面 根据http协议的规范&#xff0c;content-length响应头用来标记固定长度响应信息长度&#xff0c;http客户端&#xff0c;比如浏览器也会解析这个字段来进行数据的解析。 1&#xff1a;测试 1.1&#xff1a;content-length等于实际内容匹配时 使用python脚本testco…

T3 TensorFlow入门实战——天气识别

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習紀錄博客&#x1f356; 原作者&#xff1a;K同学啊 | 接輔導、項目定制 一、前期准备 1. 导入数据 # Import the required libraries import numpy as np import os,PIL,pathlib import matplotlib.pyplot as …

✨系统设计时应时刻考虑设计模式基础原则

目录 &#x1f4ab;单一职责原则 (Single Responsibility Principle, SRP)&#x1f4ab;开放-封闭原则 (Open-Closed Principle, OCP)&#x1f4ab;依赖倒转原则 (Dependency Inversion Principle, DIP)&#x1f4ab;里氏代换原则 (Liskov Substitution Principle, LSP)&#x…

fatal error in include chain (rtthread.h):rtconfig.h file not found

项目搜索这个文件 rtconfig 找到后将其复制粘贴到 你的目录\Keil\ARM\ARMCC\include 应该还有cJSON&#xff0c;rtthread.h和 等也复制粘贴下

【回文数组——另类递推】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int N 1e510; int a[N], b[N]; int main() {int n;cin >> n;for(int i 1; i < n; i)cin >> a[i];for(int i 1; i < n / 2; i)b[i] a[i] - a[n1-i];ll ans 0;…

SQL基础入门—— 简单查询与条件筛选

在SQL中&#xff0c;查询是从数据库中获取数据的核心操作&#xff0c;而条件筛选是查询中不可或缺的一部分。通过使用条件筛选&#xff0c;我们可以精准地从大量数据中提取我们需要的信息。本节将详细讲解如何使用SQL进行简单查询与条件筛选&#xff0c;包含常见的条件运算符和…

反向代理模块

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…