0

0

Java中基于关联键值高效过滤和移除列表对象元素教程

碧海醫心

碧海醫心

发布时间:2025-11-02 11:46:01

|

434人浏览过

|

来源于php中文网

原创

Java中基于关联键值高效过滤和移除列表对象元素教程

本文详细介绍了如何在java中高效地从一个对象列表中移除那些其特定键值不存在于另一个对象列表中的元素。教程涵盖了java 8及更高版本中利用stream api的优化方案,通过将参考列表的键收集到set中实现快速查找,以及为旧版本java提供的基于迭代器和新建列表的传统解决方案,旨在提供清晰、实用的代码示例和性能考量。

软件开发中,经常会遇到需要根据一个数据源的存在性来清理或过滤另一个数据源的场景。本教程将深入探讨如何在Java中实现这一功能,具体任务是从一个对象列表中移除那些其特定键值在另一个对象列表中不存在的元素。

问题描述

假设我们有两个不同的对象列表,每个对象都含有一个可用于关联的键。我们的目标是从第一个列表中移除所有那些其关联键在第二个列表中找不到匹配项的对象。

考虑以下两个Java类定义:

public class RetailerExcelConversionDto {
    private String retailerCode; // 关联键
    private Integer isActive;

    // 构造函数、Getter和Setter省略
    public RetailerExcelConversionDto(String retailerCode, Integer isActive) {
        this.retailerCode = retailerCode;
        this.isActive = isActive;
    }

    public String getRetailerCode() {
        return retailerCode;
    }

    public void setRetailerCode(String retailerCode) {
        this.retailerCode = retailerCode;
    }
}

public class RetailerDto {
    private String code; // 关联键
    private Integer age;
    private String name;

    // 构造函数、Getter和Setter省略
    public RetailerDto(String code, Integer age, String name) {
        this.code = code;
        this.age = age;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

我们有两个列表实例:

立即学习Java免费学习笔记(深入)”;

List retailerConversionDtoList = getAllRetailerConversionDtoList();
List retailerDtoList = getAllRetailer();

我们的任务是:从 retailerConversionDtoList 中移除所有 retailerCode 不存在于 retailerDtoList 中任何 code 的元素。

Java 8+ 优化方案:使用Stream API

Java 8引入的Stream API提供了一种声明式、函数式的方式来处理集合数据,极大地简化了集合操作。对于此类过滤需求,Stream API结合 Set 的高效查找特性,能够提供一个简洁且性能优异的解决方案。

核心思想是:

  1. 首先,从 retailerDtoList 中提取所有 code 值,并将它们收集到一个 Set 中。Set 提供了平均 O(1) 的查找时间复杂度,这对于后续的过滤操作至关重要。
  2. 然后,对 retailerConversionDtoList 应用Stream操作,使用 filter 方法保留那些其 retailerCode 存在于之前创建的 Set 中的元素。
  3. 最后,将过滤后的结果收集回一个新的 List。
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.HashSet;

// 假设 retailerExcelConversionDtoList 和 retailerDtoList 已经初始化并填充数据

// 1. 从 retailerDtoList 中提取所有 code 并放入 Set
Set retailerCodes = retailerDtoList.stream()
                                           .map(RetailerDto::getCode) // 提取 RetailerDto 对象的 code 属性
                                           .collect(Collectors.toSet()); // 收集到 Set 中

// 2. 过滤 retailerConversionDtoList
retailerConversionDtoList = retailerConversionDtoList.stream()
                                                     .filter(dto -> retailerCodes.contains(dto.getRetailerCode())) // 仅保留 retailerCode 存在于 retailerCodes Set 中的元素
                                                     .collect(Collectors.toList()); // 收集到新的 List 中

优点:

ZOER
ZOER

AI全栈应用开发平台

下载
  • 简洁性: 代码表达力强,意图清晰。
  • 效率: 利用 Set 的快速查找特性,整体时间复杂度接近 O(N+M),其中N和M分别是两个列表的大小。
  • 不变性(可选): 默认会生成一个新的列表,保留了原始列表的完整性(如果不需要原地修改)。

Java 8 以前的传统方案

对于不支持或不方便使用Java 8 Stream API的环境,我们可以采用传统的循环和迭代器方法来实现相同的功能。同样,为了优化查找性能,我们仍然会先将参考列表的键收集到一个 Set 中。

方案一:创建新列表并添加匹配项

这种方法通过遍历原始列表,将符合条件的元素添加到新列表中,最后替换掉旧列表(如果需要)。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

// 假设 retailerExcelConversionDtoList 和 retailerDtoList 已经初始化并填充数据

// 1. 从 retailerDtoList 中提取所有 code 并放入 Set
Set retailerCodes = new HashSet<>();
for (RetailerDto retailer : retailerDtoList) {
    retailerCodes.add(retailer.getCode());
}

// 2. 创建一个新列表来存储过滤后的元素
List newRetailerConversionDtoList = new ArrayList<>();
for (RetailerExcelConversionDto dto : retailerConversionDtoList) {
    if (retailerCodes.contains(dto.getRetailerCode())) {
        newRetailerConversionDtoList.add(dto);
    }
}

// 3. (可选)如果需要原地修改,将新列表赋值给原列表
retailerConversionDtoList = newRetailerConversionDtoList;

优点:

  • 兼容性: 适用于所有Java版本。
  • 安全性: 不会修改原始列表,而是创建了一个新的过滤后的列表。

缺点:

  • 需要额外的内存来存储新列表。

方案二:使用迭代器进行原地移除

如果需要在不创建新列表的情况下修改原始列表,那么使用 Iterator 是最安全和推荐的方式。直接在 for 循环中使用 list.remove(i) 会导致 IndexOutOfBoundsException 或跳过元素,因为移除元素会改变列表的大小和后续元素的索引。Iterator.remove() 方法则能够正确处理这种情况。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

// 假设 retailerExcelConversionDtoList 和 retailerDtoList 已经初始化并填充数据

// 1. 从 retailerDtoList 中提取所有 code 并放入 Set
Set retailerCodes = new HashSet<>();
for (RetailerDto retailer : retailerDtoList) {
    retailerCodes.add(retailer.getCode());
}

// 2. 使用迭代器遍历并移除不匹配的元素
for (Iterator it = retailerConversionDtoList.iterator(); it.hasNext(); ) {
    RetailerExcelConversionDto next = it.next();
    if (!retailerCodes.contains(next.getRetailerCode())) {
        it.remove(); // 使用迭代器的 remove 方法安全地移除当前元素
    }
}

优点:

  • 内存效率: 不需要额外的列表内存,直接在原列表上操作。
  • 兼容性: 适用于所有Java版本。

注意事项:

  • 只能使用 Iterator.remove(): 绝对不要在增强型 for 循环(foreach)或普通的 for 循环中使用 list.remove() 来修改正在遍历的列表,否则会抛出 ConcurrentModificationException 或导致意外行为。

总结与注意事项

  • 性能优化: 无论采用哪种方案,将参考列表的键首先收集到一个 HashSet 中是提高性能的关键。HashSet 提供了平均 O(1) 的查找时间复杂度,这比在每次过滤时遍历整个参考列表(O(M))要高效得多。
  • Java 8+ Stream API: 强烈推荐在Java 8及更高版本中使用Stream API。它不仅代码简洁,而且在内部优化上通常表现良好,并且通过声明式编程提高了代码的可读性和可维护性。
  • 原地修改 vs. 创建新列表:
    • 如果需要修改原始列表并且对内存占用敏感,使用 Iterator.remove() 是传统Java版本中的最佳选择。
    • 如果可以接受创建新列表,或者原始列表是不可变的,那么Stream API或创建新列表的传统方法更为安全和简洁。
  • 空值处理: 在实际应用中,需要考虑 retailerCode 或 code 属性可能为 null 的情况。在将键添加到 Set 或进行 contains 检查之前,最好进行 null 值判断,以避免 NullPointerException。例如,retailerDtoList.stream().map(RetailerDto::getCode).filter(Objects::nonNull).collect(Collectors.toSet());。

通过选择适合您项目Java版本和具体需求的方案,您可以高效且安全地完成列表对象的过滤和移除任务。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

438

2024.03.01

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

74

2025.12.04

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

75

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

36

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

60

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

40

2025.11.27

PHP 高并发与性能优化
PHP 高并发与性能优化

本专题聚焦 PHP 在高并发场景下的性能优化与系统调优,内容涵盖 Nginx 与 PHP-FPM 优化、Opcode 缓存、Redis/Memcached 应用、异步任务队列、数据库优化、代码性能分析与瓶颈排查。通过实战案例(如高并发接口优化、缓存系统设计、秒杀活动实现),帮助学习者掌握 构建高性能PHP后端系统的核心能力。

101

2025.10.16

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

73

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 13.9万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号