
本教程详细阐述了在Java中如何根据行的首个字段识别并删除文本文件中的重复行,并将处理后的数据存储到列表中。文章深入探讨了两种主要方法:一是利用Java Stream API的`Collectors.toMap`结合自定义合并函数直接处理字符串列表;二是引入自定义领域对象(如Company类)来封装数据,并通过对象ID进行去重,从而提升代码的可读性和维护性。教程包含详细的代码示例和实现解析。
在处理文本数据时,我们经常会遇到需要去除重复记录的场景。特别是在日志文件或数据导入导出中,如果重复的定义是基于行内某个特定字段(例如,行的第一个逗号分隔值),那么传统的List.stream().distinct()方法将无法满足需求,因为它会比较整行字符串的完全一致性。本文将介绍如何在Java中,针对以首字段作为重复判断依据的文本行,进行高效的去重操作,并将结果存储到ArrayList中。
假设我们有一个文本文件,内容如下:
123456,greenwitch street,near dominos store,Opp sandwitch company,Neyork,US,876890 123480,Postwitch street,near KFC store,Opp masala company,Newyork,US,876891 123456,Newyork street,near 100th avenue,King master company,Texas,US,10005
在这个例子中,第一行和第三行的起始数字“123456”是相同的,但行的其余部分不同。我们的目标是删除整个第三行,因为其首字段与第一行重复。
立即学习“Java免费学习笔记(深入)”;
Java 8引入的Stream API为处理集合数据提供了强大而灵活的工具。Collectors.toMap()方法特别适用于根据某个键值进行聚合或去重。其核心思想是:将每行数据解析出一个作为键(Key)的唯一标识,并将整行数据作为值(Value)存储起来。当遇到重复的键时,通过一个合并函数(mergeFunction)来决定保留哪个值。
我们将行的第一个逗号分隔值作为键。如果遇到相同的键,我们选择保留第一次出现的值(即最早的记录)。
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class DuplicateRowRemover {
public static void main(String[] args) {
List<String> sourceList = List.of(
"123456,greenwitch street,near dominos store,Opp sandwitch company,Neyork,US,876890",
"123480,Postwitch street,near KFC store,Opp masala company,Newyork,US,876891",
"123456,Newyork street,near 100th avenue,King master company,Texas,US,10005"
);
List<String> uniqueList = sourceList.stream()
.collect(Collectors.toMap(
str -> str.substring(0, str.indexOf(',')), // keyMapper: 提取第一个逗号前的子字符串作为键
Function.identity(), // valueMapper: 整行字符串作为值
(left, right) -> left // mergeFunction: 遇到重复键时,保留左边(即第一个遇到的)值
))
.values() // 获取Map中所有的值(即去重后的行)
.stream()
.toList(); // 转换为List
System.out.println("去重后的列表 (字符串方式):");
uniqueList.forEach(System.out::println);
}
}直接操作字符串虽然简单,但当数据结构复杂、字段较多时,容易出错且代码可读性差。更专业的做法是定义一个领域对象(如Company类)来封装每行数据,并通过对象的ID属性进行去重。这不仅提升了代码的类型安全性和可读性,也为后续的数据操作提供了便利。
我们将创建一个Company类来表示文本文件中的每一条公司记录。为了简洁,这里使用Lombok的@Getter和@Builder注解。
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class Company {
private long id;
private String street;
private String locationDescription;
private String companyName;
private String state;
private String country;
private String zipCode;
// 静态方法,用于将字符串行解析为Company对象
public static Company parse(String line) {
String[] arr = line.split(",");
if (arr.length < 7) { // 简单校验数据完整性
throw new IllegalArgumentException("Invalid line format: " + line);
}
return Company.builder()
.id(Long.parseLong(arr[0]))
.street(arr[1]) // 根据数据结构补充street字段
.locationDescription(arr[2])
.companyName(arr[3])
.state(arr[4])
.country(arr[5])
.zipCode(arr[6])
.build();
}
@Override
public String toString() { // 方便打印
return id + "," + street + "," + locationDescription + "," + companyName + "," + state + "," + country + "," + zipCode;
}
}注意: 原始数据中包含street字段,为了保证数据完整性,Company.parse()方法中已补充该字段的解析。
有了Company类后,我们可以先将每行字符串映射成Company对象,然后再利用Collectors.toMap以Company对象的id作为键进行去重。
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class DuplicateCompanyRemover {
public static void main(String[] args) {
List<String> sourceList = List.of(
"123456,greenwitch street,near dominos store,Opp sandwitch company,Neyork,US,876890",
"123480,Postwitch street,near KFC store,Opp masala company,Newyork,US,876891",
"123456,Newyork street,near 100th avenue,King master company,Texas,US,10005"
);
List<Company> uniqueCompanies = sourceList.stream()
.map(Company::parse) // 将每行字符串解析为Company对象
.collect(Collectors.toMap(
Company::getId, // keyMapper: 使用Company对象的ID作为键
Function.identity(), // valueMapper: Company对象本身作为值
(left, right) -> left // mergeFunction: 遇到重复ID时,保留第一个Company对象
))
.values()
.stream()
.toList();
System.out.println("\n去重后的列表 (Company对象方式):");以上就是Java中高效删除文本文件重复行:基于首字段的策略与实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号