
本教程详细介绍了如何在java中处理文本文件,根据每行记录的首个字段(例如id)删除重复行,并将去重后的数据存储到列表中。文章提供了两种主要方法:一是利用java stream api的`collectors.tomap`结合自定义合并函数直接处理字符串列表;二是建议通过引入领域对象(如`company`类)来封装数据,提高代码的可读性和可维护性,并演示了如何解析字符串到对象并进行去重操作。
在数据处理场景中,我们经常需要从文本文件中读取数据,并根据特定规则删除重复记录。一个常见的需求是,当每行记录由多个字段组成,且我们只关注某个特定字段(例如行首的ID)是否重复时,需要删除整行重复的记录。本文将介绍两种在Java中实现这一目标的高效方法。
Java 8引入的Stream API为集合操作提供了强大且简洁的工具。对于根据某个键去重并保留第一条记录的场景,Collectors.toMap 是一个非常合适的选择。
Collectors.toMap 方法通常有三个参数:
在这个场景中,我们需要将每行的第一个逗号分隔的值作为键,整行字符串作为值。当键重复时,我们选择保留第一个遇到的值。
立即学习“Java免费学习笔记(深入)”;
import java.util.List;
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: 保留原始字符串作为值
(existing, replacement) -> existing // mergeFunction: 遇到重复键时,保留已存在的(即第一个遇到的)
))
.values() // 获取Map中所有的值(即去重后的字符串)
.stream()
.toList(); // 将值转换为List
System.out.println("去重后的字符串列表:");
uniqueList.forEach(System.out::println);
}
}代码解析:
直接操作字符串虽然简洁,但当数据结构复杂或需要对字段进行更多操作时,容易出错且可读性差。更健壮的方法是定义一个领域(Domain)对象来封装每行数据,然后对这些对象进行去重操作。这不仅提高了代码的类型安全性和可读性,也为后续的数据处理提供了便利。
首先,我们定义一个 Company 类来表示文本文件中的每条记录:
import lombok.Builder;
import lombok.Getter; // 假设使用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;
}
}说明:
接下来,我们使用这个 Company 类来处理数据并去重:
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
// 假设Company类已定义如上
public class CompanyDuplicateRemover {
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对象本身作为值
(existing, replacement) -> existing // mergeFunction: 遇到重复ID时,保留第一个Company对象
))
.values() // 获取Map中所有的Company对象
.stream()
.toList(); // 将对象转换为List
System.out.println("去重后的Company对象列表:");
uniqueCompanies.forEach(company -> System.out.println(company.toString())); // 打印Company对象
}
}代码解析:
文件I/O处理: 上述示例假定数据已在 List<String> 中。在实际应用中,您需要从文本文件读取数据。可以使用 java.nio.file.Files.lines() 方法来高效地逐行读取文件内容,并直接将其作为Stream的源:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
// ... (Company 类和 Collectors.toMap 逻辑)
try (var lines = Files.lines(Paths.get("your_text_file.txt"))) {
List<Company> uniqueCompanies = lines
.map(Company::parse)
.collect(Collectors.toMap(
Company::getId,
Function.identity(),
(existing, replacement) -> existing
))
.values()
.stream()
.toList();
// 处理 uniqueCompanies
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
} catch (IllegalArgumentException e) {
System.err.println("Error parsing line: " + e.getMessage());
}错误处理:
性能与内存:
选择方法:
本文详细介绍了在Java中根据文本文件行的首个字段删除重复记录的两种有效策略。通过利用Java Stream API的 Collectors.toMap,我们可以灵活地定义去重规则。对于简单场景,直接操作字符串是快速有效的方案;而对于复杂或需要高可维护性的项目,引入领域对象并结合Stream API进行处理,无疑是更专业和健壮的选择。在实际应用中,务必结合文件I/O、错误处理和性能考量,选择最适合您需求的实现方式。
以上就是Java中基于首字段删除文本文件重复行并生成唯一记录列表的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号