0

0

Java中高效删除文本文件重复行:基于首字段的策略与实现

DDD

DDD

发布时间:2025-12-03 19:34:55

|

510人浏览过

|

来源于php中文网

原创

java中高效删除文本文件重复行:基于首字段的策略与实现

本教程详细阐述了在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免费学习笔记(深入)”;

解决方案一:利用 Collectors.toMap 直接处理字符串

Java 8引入的Stream API为处理集合数据提供了强大而灵活的工具。Collectors.toMap()方法特别适用于根据某个键值进行聚合或去重。其核心思想是:将每行数据解析出一个作为键(Key)的唯一标识,并将整行数据作为值(Value)存储起来。当遇到重复的键时,通过一个合并函数(mergeFunction)来决定保留哪个值。

Inworld.ai
Inworld.ai

InWorldAI是一个AI角色开发平台,开发者可以创建具有自然语言、上下文意识和多模态的AI角色,并可以继承到游戏和实时媒体中

下载

1. 核心原理

我们将行的第一个逗号分隔值作为键。如果遇到相同的键,我们选择保留第一次出现的值(即最早的记录)。

2. 代码实现

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);
    }
}

3. 代码解析

  • keyMapper (str -> str.substring(0, str.indexOf(','))): 这个函数负责从每行字符串中提取出作为唯一标识的键。它找到第一个逗号的位置,并截取从开头到该位置的子字符串。
  • valueMapper (Function.identity()): 这个函数指定了Map中存储的值。Function.identity()表示将当前流中的元素本身作为值。
  • mergeFunction ((left, right) -> left): 这是处理重复键的关键。当Collectors.toMap在处理流时遇到一个已经存在于Map中的键时,它会调用这个函数来决定保留哪个值。left代表Map中已有的值,right代表当前流中新遇到的值。-> left表示我们选择保留Map中已有的值,即第一个遇到的记录。如果选择-> right,则会保留最后一个遇到的记录。
  • .values().stream().toList(): 在完成收集后,Map中存储的键值对是唯一的。我们通过.values()获取所有去重后的行字符串集合,然后将其转换回List。

解决方案二:引入自定义领域对象(Domain Class)

直接操作字符串虽然简单,但当数据结构复杂、字段较多时,容易出错且代码可读性差。更专业的做法是定义一个领域对象(如Company类)来封装每行数据,并通过对象的ID属性进行去重。这不仅提升了代码的类型安全性和可读性,也为后续的数据操作提供了便利。

1. 定义领域对象

我们将创建一个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()方法中已补充该字段的解析。

2. 使用领域对象进行去重

有了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对象方式):");

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

220

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1564

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

649

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1208

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1184

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

192

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

111

2025.08.07

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

4

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.1万人学习

Java 教程
Java 教程

共578课时 | 80.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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