巧用Java 8 Stream流简化集合操作

简介: 本文详解Java 8 Stream API如何简化集合操作:通过filter筛选、map转换、collect收集等声明式方法,一行代码替代冗长for循环。以成年用户处理为例,对比传统写法,突出Stream在可读性、简洁性与可维护性上的显著优势。(239字)

在Java开发中,集合处理是日常高频操作。传统的for循环遍历、筛选、转换不仅代码冗余,可读性也差。Java 8引入的Stream流(Stream API)能以声明式的方式处理集合,让代码更简洁、易维护。本文通过简单示例,带你快速上手Stream流的核心用法。

场景说明

假设我们有一个用户列表,需要完成三个常见操作:

  1. 筛选出年龄大于18岁的成年用户;
  2. 提取这些用户的姓名并拼接成字符串;
  3. 统计成年用户的数量。

传统循环实现

先看传统for循环的写法,感受一下冗余的代码:

import java.util.ArrayList;
import java.util.List;

// 定义用户实体类
class User {
   
    private String name;
    private int age;

    // 构造方法
    public User(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    // getter方法
    public String getName() {
   
        return name;
    }

    public int getAge() {
   
        return age;
    }
}

public class StreamDemo {
   
    public static void main(String[] args) {
   
        // 初始化用户列表
        List<User> userList = new ArrayList<>();
        userList.add(new User("张三", 20));
        userList.add(new User("李四", 17));
        userList.add(new User("王五", 25));
        userList.add(new User("赵六", 16));

        // 传统方式:筛选成年用户、提取姓名、统计数量
        List<String> adultNames = new ArrayList<>();
        int adultCount = 0;
        for (User user : userList) {
   
            if (user.getAge() > 18) {
    // 筛选条件
                adultNames.add(user.getName()); // 提取姓名
                adultCount++; // 统计数量
            }
        }

        // 拼接姓名
        String nameStr = String.join(", ", adultNames);
        System.out.println("成年用户姓名:" + nameStr);
        System.out.println("成年用户数量:" + adultCount);
    }
}

Stream流实现

用Stream流重构后,代码更简洁,逻辑更清晰:

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

// 复用上面的User实体类
public class StreamOptDemo {
   
    public static void main(String[] args) {
   
        // 初始化用户列表
        List<User> userList = new ArrayList<>();
        userList.add(new User("张三", 20));
        userList.add(new User("李四", 17));
        userList.add(new User("王五", 25));
        userList.add(new User("赵六", 16));

        // Stream流方式:一站式完成筛选、转换、统计
        // 1. 筛选成年用户并提取姓名
        List<String> adultNames = userList.stream()
                .filter(user -> user.getAge() > 18) // 筛选条件:年龄>18
                .map(User::getName) // 提取姓名(方法引用)
                .collect(Collectors.toList()); // 转换为List

        // 2. 统计成年用户数量
        long adultCount = userList.stream()
                .filter(user -> user.getAge() > 18)
                .count(); // 直接统计数量

        // 3. 拼接姓名
        String nameStr = adultNames.stream().collect(Collectors.joining(", "));

        System.out.println("成年用户姓名:" + nameStr);
        System.out.println("成年用户数量:" + adultCount);
    }
}

代码解释

  1. stream():将集合转换为Stream流,开启流式操作;
  2. filter():接收Lambda表达式作为筛选条件,只保留符合条件的元素;
  3. map():对元素进行转换,这里通过User::getName(方法引用)提取用户姓名;
  4. collect():将流转换为指定集合(如Collectors.toList())或拼接字符串(Collectors.joining());
  5. count():统计流中元素的数量,返回long类型。

运行结果

两种写法的运行结果一致:

成年用户姓名:张三, 王五
成年用户数量:2

总结

  1. Stream流以声明式编程替代传统命令式循环,代码更简洁、可读性更高;
  2. 核心方法filter()(筛选)、map()(转换)、collect()(收集)是Stream流的高频用法;
  3. Stream流支持链式调用,可一站式完成多步集合操作,减少中间变量的定义。

Stream流不仅能简化集合操作,还支持并行流(parallelStream())提升大数据量处理效率,是Java 8及以上版本必备的核心技能。

相关文章
|
7月前
|
存储 缓存 Java
Java 对象内存布局:从堆内存储到伪共享优化的底层真相
Java对象内存布局是JVM核心基础:含对象头(Mark Word+Klass指针)、实例数据(字段重排序优化)和对齐填充(8字节对齐)。它直接影响内存占用、GC效率、锁升级与伪共享性能。掌握此机制,是深入理解并发优化(如@Contended)、指针压缩及高性能编程的必经之路。(239字)
665 111
|
8月前
|
SQL 缓存 算法
Java 内存模型与 volatile:并发底层的轻量级同步核心
`volatile` 是JMM核心轻量级同步关键字,通过内存屏障禁用重排、借助MESI协议保障可见性,精准解决可见性与有序性(不保证原子性),是DCL单例、状态标志等场景的基石,堪称高效并发编程的“轻量级钥匙”。(239字)
472 7
|
7月前
|
安全 编译器 C语言
C语言「宏的暗门」:预处理阶段的隐形篡改与避坑守则
宏是C语言预处理阶段的纯文本替换工具,无类型、无作用域、不检语法,易引发括号缺失、副作用、分号错误、类型混乱和命名污染等六大陷阱。安全使用须严守括号规范、避免参数复用、善用`do{...}while(0)`、优先选用内联函数,并及时`#undef`。(239字)
514 10
|
7月前
|
存储 网络协议 安全
C语言「内存对齐潜规则」:结构体里看不见的填充字节
内存对齐是CPU硬件要求的数据地址约束规则:变量须存于其字节大小的整数倍地址。编译器自动插入填充字节确保对齐,导致结构体体积“膨胀”、硬件寄存器读写错位或协议异常。合理排序成员(从大到小)、慎用`packed`、明确对齐控制,是嵌入式与底层开发的关键避坑要点。(239字)
|
7月前
|
人工智能 安全 编译器
C语言的「隐形时序契约」:序列点、副作用与求值顺序终极拆解
本文深入解析C语言中极易被忽视的“序列点”机制,揭示Debug/Release模式差异、跨平台结果不一致等玄学bug的根源——未定义行为(UB)。从副作用定义出发,系统梳理7类标准序列点,剖析4大高频陷阱(如`i=i++ + ++i`),并提供6条安全编码铁律,助你写出稳定、可移植的C代码。(239字)
597 11
|
7月前
|
缓存 前端开发 JavaScript
前端渲染性能的底层逻辑:跳出重排重绘的表层认知
本文揭示前端渲染优化的本质:性能瓶颈不在“重排重绘”本身,而在于浏览器渲染流水线(JS→样式→布局→绘制→合成)的**触发频次与全链路开销**。主流框架的优化逻辑——批量更新、精准更新、合成层隔离——正是围绕降低流水线调用成本展开。落地只需三招:收敛更新时机、善用编译期优化、慎用合成层。
|
7月前
|
编译器 C语言 开发者
C语言「常量折叠」:编译器的隐形优化陷阱,90%开发者踩过的常量计算骗局
C语言常量折叠是编译器在编译期预计算常量表达式(如`10+20→30`)的优化机制,可提升运行效率,却易致调试困惑、嵌入式寄存器操作失效等陷阱。关键要分清字面量/宏/enum(真常量)与`const`变量(仅只读),慎用宏、禁用`volatile`参与折叠,并合理控制优化等级。
|
7月前
|
缓存 编译器 程序员
C语言深度解析:restrict关键字——编译器性能优化的终极钥匙
C99的`restrict`关键字是C语言性能优化的“终极钥匙”:它向编译器承诺指针独占访问内存,彻底解决同类型指针别名问题,解锁循环向量化、寄存器缓存等激进优化。滥用致未定义行为,善用则性能飙升数倍——这才是真正高阶C程序员的必修课。(239字)
1035 7
|
7月前
|
存储 安全 编译器
C语言「存储期四象限」:变量生死的底层宪法,90%内存bug的根源
本文深入剖析C语言四大存储期(静态、自动、分配、线程),揭示“变量消失”“指针错乱”“内存泄漏”等顽疾的根源——**访问了生命周期已结束的内存**。用四象限模型厘清变量生死规则,助你从底层杜绝90%内存bug。(239字)
487 15
|
7月前
|
JavaScript 前端开发 Java
闭包:被误解最深的 JavaScript 特性
闭包本质是JS保留作用域上下文的能力,非语法而是引擎机制。它支撑私有变量封装、模块化与防抖/节流等高级模式。内存泄漏主因是未及时解除引用,而非闭包本身。理解闭包,方懂JS作用域与生命周期精髓。(239字)