0

0

Java中基于关联键移除列表对象教程

霞舞

霞舞

发布时间:2025-11-02 15:31:21

|

662人浏览过

|

来源于php中文网

原创

Java中基于关联键移除列表对象教程

本教程详细介绍了如何在java中高效地从一个对象列表中移除那些其特定键值在另一个对象列表中不存在的项。文章涵盖了java 8及更高版本中利用stream api的现代化解决方案,以及java 8之前版本通过传统循环和迭代器实现的方法,并对不同方法的性能和适用场景进行了深入分析,旨在帮助开发者选择最优化策略。

1. 定义数据模型

首先,我们定义两个用于示例的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 Integer getIsActive() {
        return isActive;
    }

    public void setIsActive(Integer isActive) {
        this.isActive = isActive;
    }
}

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;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

假设我们有以下两个列表实例:

List retailerConversionDtoList = new ArrayList<>();
// 填充数据...
retailerConversionDtoList.add(new RetailerExcelConversionDto("R001", 1));
retailerConversionDtoList.add(new RetailerExcelConversionDto("R002", 1));
retailerConversionDtoList.add(new RetailerExcelConversionDto("R003", 0));

List retailerDtoList = new ArrayList<>();
// 填充数据...
retailerDtoList.add(new RetailerDto("R001", 30, "Retailer A"));
retailerDtoList.add(new RetailerDto("R004", 25, "Retailer D"));

2. 核心问题阐述

我们的目标是从 retailerConversionDtoList 中移除所有 retailerCode 不存在于 retailerDtoList 中任何 code 的项。简而言之,我们希望保留 retailerConversionDtoList 中与 retailerDtoList 存在关联(通过编码匹配)的项。

3. 解决方案一:使用 Java 8 Stream API (推荐)

在 Java 8 及更高版本中,Stream API 提供了一种简洁且高效的方式来处理集合数据。这种方法利用 Set 的快速查找特性,优化了移除操作。

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

实现步骤:

Perl 基础教程 chm
Perl 基础教程 chm

Perl 基础入门中文教程,chm格式,讲述PERL概述、简单变量、操作符、列表和数组变量、文件读写、模式匹配、控制结构、子程序、关联数组/哈希表、格式化输出、文件系统、引用、面向对象、包和模块等知识点。适合初学者阅读和了解Perl脚本语言。

下载
  1. 从 retailerDtoList 中提取所有 code 属性,并将它们收集到一个 Set 中。使用 Set 的目的是为了实现 O(1) 的平均查找时间复杂度,而非 List 的 O(N),这在数据量较大时能显著提升性能。
  2. 使用 Stream API 过滤 retailerConversionDtoList。对于 retailerConversionDtoList 中的每个元素,检查其 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; // 导入 HashSet 以便构建示例数据

// 假设 RetailerExcelConversionDto 和 RetailerDto 类已定义

public class ListRemovalWithStream {

    public static void main(String[] args) {
        // 示例数据
        List retailerConversionDtoList = new ArrayList<>();
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R001", 1));
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R002", 1));
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R003", 0));
        System.out.println("原始 retailerConversionDtoList: " + retailerConversionDtoList.stream().map(RetailerExcelConversionDto::getRetailerCode).collect(Collectors.toList()));

        List retailerDtoList = new ArrayList<>();
        retailerDtoList.add(new RetailerDto("R001", 30, "Retailer A"));
        retailerDtoList.add(new RetailerDto("R004", 25, "Retailer D"));
        System.out.println("参照 retailerDtoList codes: " + retailerDtoList.stream().map(RetailerDto::getCode).collect(Collectors.toList()));

        // 步骤 1: 提取所有存在的 retailer codes 到一个 Set 中
        Set retailerCodes = retailerDtoList.stream()
                                                    .map(RetailerDto::getCode)
                                                    .collect(Collectors.toSet());

        // 步骤 2 & 3: 过滤 retailerConversionDtoList
        retailerConversionDtoList = retailerConversionDtoList.stream()
                                                            .filter(t -> retailerCodes.contains(t.getRetailerCode()))
                                                            .collect(Collectors.toList());

        System.out.println("过滤后的 retailerConversionDtoList: " + retailerConversionDtoList.stream().map(RetailerExcelConversionDto::getRetailerCode).collect(Collectors.toList()));
        // 预期输出: [R001]
    }
}

优点:

  • 代码简洁: Stream API 提供了声明式编程风格,使代码更易读、更简洁。
  • 效率高: 利用 Set 进行查找,时间复杂度接近 O(N + M),其中 N 和 M 分别是两个列表的大小。
  • 函数式编程: 更好地支持函数式编程范式,易于并行化(尽管在此场景下可能不需要)。

4. 解决方案二:Java 8 之前的传统方法

对于不支持 Java 8 Stream API 的旧版本 Java 环境,我们可以通过传统的循环和迭代器来实现相同的功能。

4.1 方法一:构建新列表

这种方法与 Stream API 的逻辑类似,都是先构建一个用于查找的 Set,然后遍历原列表,将符合条件的元素添加到一个新列表中。

实现步骤:

  1. 创建一个 HashSet 用于存储 retailerDtoList 中所有 code。
  2. 遍历 retailerDtoList,将每个 RetailerDto 对象的 code 添加到 HashSet 中。
  3. 创建一个新的 List 来存储过滤后的结果。
  4. 遍历 retailerConversionDtoList。对于每个元素,检查其 retailerCode 是否存在于 HashSet 中。如果存在,则将其添加到新列表中。

示例代码:

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

public class ListRemovalTraditionalNewList {

    public static void main(String[] args) {
        // 示例数据 (同上)
        List retailerConversionDtoList = new ArrayList<>();
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R001", 1));
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R002", 1));
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R003", 0));
        System.out.println("原始 retailerConversionDtoList: " + retailerConversionDtoList.stream().map(RetailerExcelConversionDto::getRetailerCode).collect(Collectors.toList()));

        List retailerDtoList = new ArrayList<>();
        retailerDtoList.add(new RetailerDto("R001", 30, "Retailer A"));
        retailerDtoList.add(new RetailerDto("R004", 25, "Retailer D"));
        System.out.println("参照 retailerDtoList codes: " + retailerDtoList.stream().map(RetailerDto::getCode).collect(Collectors.toList()));

        // 步骤 1 & 2: 提取所有存在的 retailer codes 到一个 Set 中
        Set retailerCodes = new HashSet<>();
        for (RetailerDto retailer : retailerDtoList) {
            retailerCodes.add(retailer.getCode());
        }

        // 步骤 3 & 4: 遍历并构建新列表
        List newRetailerConversionDtoList = new ArrayList<>();
        for (RetailerExcelConversionDto item : retailerConversionDtoList) {
            if (retailerCodes.contains(item.getRetailerCode())) {
                newRetailerConversionDtoList.add(item);
            }
        }
        retailerConversionDtoList = newRetailerConversionDtoList; // 更新引用到新列表

        System.out.println("过滤后的 retailerConversionDtoList: " + retailerConversionDtoList.stream().map(RetailerExcelConversionDto::getRetailerCode).collect(Collectors.toList()));
        // 预期输出: [R001]
    }
}

优点:

  • 兼容性好: 适用于所有 Java 版本。
  • 逻辑清晰: 循环和条件判断直观易懂。

缺点:

  • 内存开销: 需要创建一个新的列表,如果原始列表很大,可能会有额外的内存开销。
  • 代码冗长: 相较于 Stream API,代码量更多。

4.2 方法二:使用迭代器原地移除

如果需要直接修改原始列表而不是创建新列表,可以使用迭代器(Iterator)的 remove() 方法。注意:在循环遍历集合时,直接使用增强for循环(for-each)或普通 for 循环通过索引移除元素会导致 ConcurrentModificationException 或跳过元素。 迭代器的 remove() 方法是唯一安全的在遍历时修改集合的方式。

实现步骤:

  1. 创建一个 HashSet 用于存储 retailerDtoList 中所有 code。
  2. 获取 retailerConversionDtoList 的迭代器。
  3. 使用 while (iterator.hasNext()) 循环遍历列表。
  4. 在循环中,获取当前元素,并检查其 retailerCode 是否存在于 HashSet 中。
  5. 如果 retailerCode 不存在于 HashSet 中,则使用 iterator.remove() 方法将当前元素从列表中移除。

示例代码:

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

public class ListRemovalTraditionalIterator {

    public static void main(String[] args) {
        // 示例数据 (同上)
        List retailerConversionDtoList = new ArrayList<>();
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R001", 1));
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R002", 1));
        retailerConversionDtoList.add(new RetailerExcelConversionDto("R003", 0));
        System.out.println("原始 retailerConversionDtoList: " + retailerConversionDtoList.stream().map(RetailerExcelConversionDto::getRetailerCode).collect(Collectors.toList()));

        List retailerDtoList = new ArrayList<>();
        retailerDtoList.add(new RetailerDto("R001", 30, "Retailer A"));
        retailerDtoList.add(new RetailerDto("R004", 25, "Retailer D"));
        System.out.println("参照 retailerDtoList codes: " + retailerDtoList.stream().map(RetailerDto::getCode).collect(Collectors.toList()));

        // 步骤 1: 提取所有存在的 retailer codes 到一个 Set 中
        Set retailerCodes = new HashSet<>();
        for (RetailerDto retailer : retailerDtoList) {
            retailerCodes.add(retailer.getCode());
        }

        // 步骤 2-5: 使用迭代器原地移除
        for (Iterator it = retailerConversionDtoList.iterator(); it.hasNext(); ) {
            RetailerExcelConversionDto next = it.next();
            if (!retailerCodes.contains(next.getRetailerCode())) {
                it.remove(); // 如果不存在,则移除
            }
        }

        System.out.println("过滤后的 retailerConversionDtoList: " + retailerConversionDtoList.stream().map(RetailerExcelConversionDto::getRetailerCode).collect(Collectors.toList()));
        // 预期输出: [R001]
    }
}

优点:

  • 节省内存: 直接修改原始列表,无需创建新列表。
  • 兼容性好: 适用于所有 Java 版本。

缺点:

  • 代码相对复杂: 迭代器操作不如 Stream API 直观。
  • 易错性: 如果不正确使用迭代器(例如,在增强for循环中尝试修改),很容易导致运行时错误。

5. 性能考量与最佳实践

  • 使用 Set 进行查找: 无论采用哪种方法,将参照列表的键值收集到 HashSet 中都是至关重要的优化步骤。HashSet 提供了平均 O(1) 的查找时间复杂度,而 ArrayList 或 LinkedList 的 contains() 方法是 O(N),这将极大地影响整体性能,尤其是在列表数据量较大时。
  • Java 8+ 优先选择 Stream API: Stream API 结合 filter 和 collect 提供了最简洁、可读性高且性能优越的解决方案。它避免了手动管理迭代器,并且在内部实现上通常经过优化。
  • 旧版本 Java 的选择:
    • 如果内存不是瓶颈,并且希望代码更直观,可以选择“构建新列表”的方法。
    • 如果对内存使用有严格要求,且愿意处理迭代器逻辑,可以选择“使用迭代器原地移除”的方法。务必正确使用 Iterator.remove()。

6. 总结

本文详细介绍了在 Java 中根据关联键从一个对象列表中移除项的多种方法。对于 Java 8 及更高版本,推荐使用 Stream API 结合 Set 进行高效过滤,它提供了最佳的简洁性和性能平衡。对于旧版本 Java,通过将参照键存储在 HashSet 中,然后选择构建新列表或使用迭代器原地移除,也能实现相同的目标。理解不同方法的优缺点和适用场景,有助于开发者在实际项目中做出明智的选择,编写出更健壮、高效的代码。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

443

2023.08.02

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

94

2023.09.25

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

109

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

16

2026.01.26

苹果官方查询网站 苹果手机正品激活查询入口
苹果官方查询网站 苹果手机正品激活查询入口

苹果官方查询网站主要通过 checkcoverage.apple.com/cn/zh/ 进行,可用于查询序列号(SN)对应的保修状态、激活日期及技术支持服务。此外,查找丢失设备请使用 iCloud.com/find,购买信息与物流可访问 Apple (中国大陆) 订单状态页面。

138

2026.01.26

npd人格什么意思 npd人格有什么特征
npd人格什么意思 npd人格有什么特征

NPD(Narcissistic Personality Disorder)即自恋型人格障碍,是一种心理健康问题,特点是极度夸大自我重要性、需要过度赞美与关注,同时极度缺乏共情能力,背后常掩藏着低自尊和不安全感,影响人际关系、工作和生活,通常在青少年时期开始显现,需由专业人士诊断。

7

2026.01.26

windows安全中心怎么关闭 windows安全中心怎么执行操作
windows安全中心怎么关闭 windows安全中心怎么执行操作

关闭Windows安全中心(Windows Defender)可通过系统设置暂时关闭,或使用组策略/注册表永久关闭。最简单的方法是:进入设置 > 隐私和安全性 > Windows安全中心 > 病毒和威胁防护 > 管理设置,将实时保护等选项关闭。

6

2026.01.26

2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】
2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】

铁路12306提供起售时间查询、起售提醒、购票预填、候补购票及误购限时免费退票五项服务,并强调官方渠道唯一性与信息安全。

122

2026.01.26

热门下载

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

精品课程

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

共162课时 | 13.8万人学习

成为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号