
本教程详细介绍了如何在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免费学习笔记(深入)”;
Java 8引入的Stream API提供了一种声明式、函数式的方式来处理集合数据,极大地简化了代码并提高了可读性。结合 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) 复杂度,这是一个显著的性能提升。
在Java 8之前的版本中,由于没有Stream API,我们需要通过传统的循环和集合操作来实现相同的功能。同样,利用 Set 进行查找仍然是优化性能的关键。
核心思路:
这种方法是创建并返回一个符合条件的新列表,原始列表保持不变。
示例代码:
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如果需要直接修改原始列表而不是创建新列表,那么在循环中移除元素时必须使用 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, R003retailerConversionDtoList.removeIf(item -> !retailerCodes.contains(item.getRetailerCode()));
这种方式比手动使用 Iterator 更简洁。
高效地从一个列表中移除基于另一个列表的关联键值不存在的元素,关键在于利用 Set 的快速查找能力。对于Java 8及更高版本,Stream API提供了极其简洁和强大的解决方案。而在Java 8之前,虽然需要更多手动循环,但通过将查找键预先加载到 HashSet 中,依然可以实现高性能的数据过滤。选择哪种方法取决于你的Java版本和对代码风格、可变性需求的偏好。
以上就是Java中根据关联键值高效过滤列表元素教程的详细内容,更多请关注php中文网其它相关文章!
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号