首页 > Java > java教程 > 正文

Java中根据关联键值高效过滤列表元素教程

DDD
发布: 2025-11-02 15:51:01
原创
327人浏览过

Java中根据关联键值高效过滤列表元素教程

本教程详细介绍了如何在java中高效地从一个对象列表中移除那些其特定键值不存在于另一个对象列表中的元素。文章将分别探讨java 8及更高版本中利用stream api和set进行优化的解决方案,以及java 8之前版本通过传统循环和迭代器实现相同功能的策略,并强调了性能优化和代码可读性的关键点。

在Java开发中,我们经常会遇到需要根据一个列表的特定属性,来筛选或修改另一个列表的需求。例如,给定两个包含不同类型对象的列表,我们可能需要从第一个列表中移除所有其某个关键属性值在第二个列表中不存在的元素。本文将以具体示例深入探讨如何高效地实现这一目标。

假设我们有以下两个数据传输对象(DTO)类:

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 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;
    }
}
登录后复制

并且我们拥有这两个类的实例列表:

List<RetailerExcelConversionDto> retailerConversionDtoList = getAllRetailerConversionDtoList();
List<RetailerDto> retailerDtoList = getAllRetailer();
登录后复制

我们的目标是从 retailerConversionDtoList 中移除所有 retailerCode 属性值在 retailerDtoList 的 code 属性值中不存在的元素。

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

1. 现代Java (Java 8+) 的解决方案:利用Stream API

Java 8引入的Stream API提供了一种声明式、函数式的方式来处理集合数据,极大地简化了代码并提高了可读性。结合 Set 的高效查找特性,我们可以以非常优化的方式解决这个问题。

核心思路:

  1. 从 retailerDtoList 中提取所有 code 属性值,并将它们收集到一个 Set 中。Set 提供了平均 O(1) 的查找时间复杂度,这对于后续的过滤操作至关重要。
  2. 对 retailerConversionDtoList 使用Stream API进行过滤,只保留那些 retailerCode 存在于之前构建的 Set 中的元素。

示例代码:

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Arrays; // 仅用于示例数据

// 假设 getAllRetailerConversionDtoList() 和 getAllRetailer() 已经实现
// 模拟数据
List<RetailerExcelConversionDto> retailerConversionDtoList = Arrays.asList(
    new RetailerExcelConversionDto("R001", 1),
    new RetailerExcelConversionDto("R002", 0),
    new RetailerExcelConversionDto("R003", 1),
    new RetailerExcelConversionDto("R005", 1) // R005 不存在于 retailerDtoList
);

List<RetailerDto> retailerDtoList = Arrays.asList(
    new RetailerDto("R001", 30, "Retailer A"),
    new RetailerDto("R002", 25, "Retailer B"),
    new RetailerDto("R003", 35, "Retailer C"),
    new RetailerDto("R004", 40, "Retailer D")
);

// 步骤1: 提取 retailerDtoList 中的所有 code 到一个 Set
Set<String> retailerCodes = retailerDtoList.stream()
                                         .map(RetailerDto::getCode) // 或者 t -> t.getCode()
                                         .collect(Collectors.toSet());

// 步骤2: 过滤 retailerConversionDtoList,只保留 retailerCode 存在于 retailerCodes Set 中的元素
retailerConversionDtoList = retailerConversionDtoList.stream()
                                                    .filter(t -> retailerCodes.contains(t.getRetailerCode())) // 或者 RetailerExcelConversionDto::getRetailerCode
                                                    .collect(Collectors.toList());

// 此时 retailerConversionDtoList 将只包含 R001, R002, R003
retailerConversionDtoList.forEach(r -> System.out.println(r.getRetailerCode()));
// 预期输出: R001, R002, R003
登录后复制

这种方法利用了 Set 的高效查找能力(平均 O(1)),使得整个过滤过程的时间复杂度接近 O(N + M),其中 N 是 retailerConversionDtoList 的大小,M 是 retailerDtoList 的大小。相比于嵌套循环的 O(N*M) 复杂度,这是一个显著的性能提升。

酷表ChatExcel
酷表ChatExcel

北大团队开发的通过聊天来操作Excel表格的AI工具

酷表ChatExcel 48
查看详情 酷表ChatExcel

2. 传统Java (Java 8之前) 的解决方案

在Java 8之前的版本中,由于没有Stream API,我们需要通过传统的循环和集合操作来实现相同的功能。同样,利用 Set 进行查找仍然是优化性能的关键。

核心思路:

  1. 首先,遍历 retailerDtoList,将其所有 code 属性值收集到一个 HashSet 中。
  2. 然后,根据需求选择以下两种方式之一来过滤 retailerConversionDtoList。

2.1. 构建一个新的列表

这种方法是创建并返回一个符合条件的新列表,原始列表保持不变。

示例代码:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Arrays; // 仅用于示例数据

// 模拟数据
List<RetailerExcelConversionDto> retailerConversionDtoList = Arrays.asList(
    new RetailerExcelConversionDto("R001", 1),
    new RetailerExcelConversionDto("R002", 0),
    new RetailerExcelConversionDto("R003", 1),
    new RetailerExcelConversionDto("R005", 1)
);

List<RetailerDto> retailerDtoList = Arrays.asList(
    new RetailerDto("R001", 30, "Retailer A"),
    new RetailerDto("R002", 25, "Retailer B"),
    new RetailerDto("R003", 35, "Retailer C"),
    new RetailerDto("R004", 40, "Retailer D")
);

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

// 步骤2: 遍历 retailerConversionDtoList,将符合条件的元素添加到新列表
List<RetailerExcelConversionDto> newRetailerConversionDtoList = new ArrayList<>();
for (RetailerExcelConversionDto item : retailerConversionDtoList) {
    if (retailerCodes.contains(item.getRetailerCode())) {
        newRetailerConversionDtoList.add(item);
    }
}

// 现在 newRetailerConversionDtoList 包含过滤后的元素
newRetailerConversionDtoList.forEach(r -> System.out.println(r.getRetailerCode()));
// 预期输出: R001, R002, R003
登录后复制

2.2. 使用迭代器在原列表上移除元素

如果需要直接修改原始列表而不是创建新列表,那么在循环中移除元素时必须使用 Iterator。直接在增强型 for 循环(for-each loop)中调用 list.remove() 会导致 ConcurrentModificationException。

示例代码:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Arrays; // 仅用于示例数据

// 模拟数据
List<RetailerExcelConversionDto> retailerConversionDtoList = new ArrayList<>(Arrays.asList( // 注意这里需要可变列表
    new RetailerExcelConversionDto("R001", 1),
    new RetailerExcelConversionDto("R002", 0),
    new RetailerExcelConversionDto("R003", 1),
    new RetailerExcelConversionDto("R005", 1)
));

List<RetailerDto> retailerDtoList = Arrays.asList(
    new RetailerDto("R001", 30, "Retailer A"),
    new RetailerDto("R002", 25, "Retailer B"),
    new RetailerDto("R003", 35, "Retailer C"),
    new RetailerDto("R004", 40, "Retailer D")
);

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

// 步骤2: 使用迭代器遍历 retailerConversionDtoList 并移除不符合条件的元素
Iterator<RetailerExcelConversionDto> iterator = retailerConversionDtoList.iterator();
while (iterator.hasNext()) {
    RetailerExcelConversionDto item = iterator.next();
    if (!retailerCodes.contains(item.getRetailerCode())) {
        iterator.remove(); // 使用迭代器安全地移除元素
    }
}

// 现在 retailerConversionDtoList 已经被修改
retailerConversionDtoList.forEach(r -> System.out.println(r.getRetailerCode()));
// 预期输出: R001, R002, R003
登录后复制

3. 注意事项与性能考量

  • 使用 Set 进行查找: 无论是Java 8+还是Java 8之前的版本,将用于比较的键值集合存储在 HashSet 中是实现高效过滤的关键。HashSet 提供了平均 O(1) 的查找时间复杂度,而 ArrayList 的 contains() 方法是 O(N),这在处理大量数据时会导致巨大的性能差异。
  • Stream API 的优势: Java 8的Stream API不仅代码更简洁、可读性更高,而且在某些情况下(如并行流)还能提供性能上的优势。它鼓励函数式编程范式,使得数据转换和过滤操作更加流畅。
  • 修改列表时的选择:
    • 如果可以接受创建一个新列表,那么构建新列表(如Stream API的 collect(Collectors.toList()) 或传统方式中的 new ArrayList<>())通常是更安全、更简洁的选择。
    • 如果必须在原地修改原始列表,并且是Java 8之前的版本,则必须使用 Iterator 的 remove() 方法。Java 8+ 可以使用 List.removeIf() 方法,它内部也是通过迭代器实现的,但提供了更简洁的语法。
    • 例如,在Java 8+中,原地修改也可以这样实现:
      retailerConversionDtoList.removeIf(item -> !retailerCodes.contains(item.getRetailerCode()));
      登录后复制

      这种方式比手动使用 Iterator 更简洁。

  • 对象属性的访问: 确保你的DTO类有相应的getter方法,或者如果属性是public的,可以直接访问。在Stream API中,可以使用方法引用(如 RetailerDto::getCode)或Lambda表达式(如 t -> t.getCode())。

总结

高效地从一个列表中移除基于另一个列表的关联键值不存在的元素,关键在于利用 Set 的快速查找能力。对于Java 8及更高版本,Stream API提供了极其简洁和强大的解决方案。而在Java 8之前,虽然需要更多手动循环,但通过将查找键预先加载到 HashSet 中,依然可以实现高性能的数据过滤。选择哪种方法取决于你的Java版本和对代码风格、可变性需求的偏好。

以上就是Java中根据关联键值高效过滤列表元素教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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