
本教程详细介绍了如何在java中高效地从一个对象列表中移除那些其特定键值在另一个对象列表中不存在的项。文章涵盖了java 8及更高版本中利用stream api的现代化解决方案,以及java 8之前版本通过传统循环和迭代器实现的方法,并对不同方法的性能和适用场景进行了深入分析,旨在帮助开发者选择最优化策略。
首先,我们定义两个用于示例的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<RetailerExcelConversionDto> retailerConversionDtoList = new ArrayList<>();
// 填充数据...
retailerConversionDtoList.add(new RetailerExcelConversionDto("R001", 1));
retailerConversionDtoList.add(new RetailerExcelConversionDto("R002", 1));
retailerConversionDtoList.add(new RetailerExcelConversionDto("R003", 0));
List<RetailerDto> retailerDtoList = new ArrayList<>();
// 填充数据...
retailerDtoList.add(new RetailerDto("R001", 30, "Retailer A"));
retailerDtoList.add(new RetailerDto("R004", 25, "Retailer D"));我们的目标是从 retailerConversionDtoList 中移除所有 retailerCode 不存在于 retailerDtoList 中任何 code 的项。简而言之,我们希望保留 retailerConversionDtoList 中与 retailerDtoList 存在关联(通过编码匹配)的项。
在 Java 8 及更高版本中,Stream API 提供了一种简洁且高效的方式来处理集合数据。这种方法利用 Set 的快速查找特性,优化了移除操作。
立即学习“Java免费学习笔记(深入)”;
实现步骤:
示例代码:
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<RetailerExcelConversionDto> 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<RetailerDto> 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<String> 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]
}
}优点:
对于不支持 Java 8 Stream API 的旧版本 Java 环境,我们可以通过传统的循环和迭代器来实现相同的功能。
这种方法与 Stream API 的逻辑类似,都是先构建一个用于查找的 Set,然后遍历原列表,将符合条件的元素添加到一个新列表中。
实现步骤:
示例代码:
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<RetailerExcelConversionDto> 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<RetailerDto> 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<String> retailerCodes = new HashSet<>();
for (RetailerDto retailer : retailerDtoList) {
retailerCodes.add(retailer.getCode());
}
// 步骤 3 & 4: 遍历并构建新列表
List<RetailerExcelConversionDto> 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]
}
}优点:
缺点:
如果需要直接修改原始列表而不是创建新列表,可以使用迭代器(Iterator)的 remove() 方法。注意:在循环遍历集合时,直接使用增强for循环(for-each)或普通 for 循环通过索引移除元素会导致 ConcurrentModificationException 或跳过元素。 迭代器的 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<RetailerExcelConversionDto> 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<RetailerDto> 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<String> retailerCodes = new HashSet<>();
for (RetailerDto retailer : retailerDtoList) {
retailerCodes.add(retailer.getCode());
}
// 步骤 2-5: 使用迭代器原地移除
for (Iterator<RetailerExcelConversionDto> 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 中根据关联键从一个对象列表中移除项的多种方法。对于 Java 8 及更高版本,推荐使用 Stream API 结合 Set 进行高效过滤,它提供了最佳的简洁性和性能平衡。对于旧版本 Java,通过将参照键存储在 HashSet 中,然后选择构建新列表或使用迭代器原地移除,也能实现相同的目标。理解不同方法的优缺点和适用场景,有助于开发者在实际项目中做出明智的选择,编写出更健壮、高效的代码。
以上就是Java中基于关联键移除列表对象教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号