0

0

Java Stream API实现姓名解析与分离:从全名字符串提取姓氏与名字

霞舞

霞舞

发布时间:2025-12-03 18:59:09

|

470人浏览过

|

来源于php中文网

原创

Java Stream API实现姓名解析与分离:从全名字符串提取姓氏与名字

本文旨在指导如何在java中高效处理包含多个全名字符串的数组列表,并利用stream api将每个全名拆分为名字和姓氏。教程将详细讲解如何通过查找最后一个空格来区分名字和姓氏,并演示如何将解析结果存储到新的字符串数组或更符合面向对象设计的`author`对象列表中,从而提升数据处理的灵活性和代码的可读性。

1. 问题背景与目标

在处理从外部数据源(如CSV文件)读取的姓名数据时,我们经常会遇到需要将一个完整的姓名字符串拆分为名字(First Name)和姓氏(Last Name)的需求。例如,从CSV文件中读取的作者列表可能以 String[] 的形式存在,其中每个元素都是一个完整的作者姓名,如 "Christian Janze" 或 "Kenan Xiao Auburn University"。我们的目标是:

  1. 从这些全名字符串中分离出名字和姓氏。
  2. 假设一个全名字符串中,最后一个单词是姓氏,其余部分是名字。
  3. 将分离后的名字和姓氏存储起来,以便后续处理。

原始数据结构通常是一个 ArrayList,其中每个 String[] 代表一组作者,每个 String 是一个全名。

2. 原始数据结构与示例

假设我们已经从CSV文件中读取了作者姓名,并将其存储在一个 ArrayList 中,其内容可能如下:

// 假设 authorGroups 已经通过文件读取填充
ArrayList<String[]> authorGroups = new ArrayList<>();
// 示例数据,实际数据可能来自文件读取
authorGroups.add(new String[]{"Christian Janze", "Marten Risius"});
authorGroups.add(new String[]{"Kenan Xiao Auburn University", "Ashish Gupta", "Wenting Jiang", "Xiao Qin"});
authorGroups.add(new String[]{"Kyuhan Lee", "Sudha Ram"});
authorGroups.add(new String[]{"Kelvin King-Kizito"});

System.out.println("原始作者姓名组列表:");
for (String[] group : authorGroups) {
    System.out.println(Arrays.toString(group));
}
/* 
输出示例:
原始作者姓名组列表:
[Christian Janze, Marten Risius]
[Kenan Xiao Auburn University, Ashish Gupta, Wenting Jiang, Xiao Qin]
[Kyuhan Lee, Sudha Ram]
[Kelvin King-Kizito]
*/

我们的任务是将每个全名字符串(例如 "Christian Janze")拆分为 "Christian"(名字)和 "Janze"(姓氏)。

立即学习Java免费学习笔记(深入)”;

3. 基于Java Stream API的姓名解析方案

Java 8引入的Stream API提供了一种声明式且高效的方式来处理集合数据。我们可以利用它来遍历 authorGroups,对每个全名字符串执行解析操作,并收集结果。

3.1 核心解析逻辑详解

对于每个全名字符串,我们需要找到最后一个空格的位置。这个空格将作为名字和姓氏的分隔符。

  • strArr[i].lastIndexOf(" "):找到字符串中最后一个空格的索引。
  • strArr[i].substring(0, lastIndexOfWhitespace):从字符串开头到最后一个空格之前的部分,作为名字。
  • strArr[i].substring(lastIndexOfWhitespace + 1):从最后一个空格之后的部分到字符串结尾,作为姓氏。

我们将为每个原始全名生成两个新的字符串(名字和姓氏),并将它们存储在一个新的 String[] 中。

Memo AI
Memo AI

AI音视频转文字及字幕翻译工具

下载

3.2 完整代码实现

以下代码片段展示了如何使用Stream API来执行姓名解析和分离:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class NameParser {

    // 假设 Author 类如问题描述所示
    public static class Author {
        private String name;
        private String surname;

        public Author(String name, String surname) {
            this.name = name;
            this.surname = surname;
        }

        public String getName() {
            return name;
        }

        public String getSurname() {
            return surname;
        }

        @Override
        public String toString() {
            return "Author{" + "name='" + name + '\'' + ", surname='" + surname + '\'' + '}';
        }
    }

    public static void main(String[] args) {
        ArrayList<String[]> authorGroups = new ArrayList<>();
        authorGroups.add(new String[]{"Christian Janze", "Marten Risius"});
        authorGroups.add(new String[]{"Kenan Xiao Auburn University", "Ashish Gupta", "Wenting Jiang", "Xiao Qin"});
        authorGroups.add(new String[]{"Kyuhan Lee", "Sudha Ram"});
        authorGroups.add(new String[]{"Kelvin King-Kizito"});
        authorGroups.add(new String[]{"SingleName"}); // 示例:一个单词的姓名

        System.out.println("--- 原始作者姓名组列表 ---");
        for (String[] group : authorGroups) {
            System.out.println(Arrays.toString(group));
        }

        // 使用 Stream API 分离姓名,结果存储为 ArrayList<String[]>
        ArrayList<String[]> authorGroupsWithSeparatedNames = authorGroups.stream()
            .map(strArr -> { // 对每个 String[] 进行处理
                // 新的数组将存储分离后的名字和姓氏,长度是原数组的两倍
                String[] newStrArr = new String[strArr.length * 2];
                for (int i = 0; i < strArr.length; i++) {
                    String fullName = strArr[i].trim(); // 清除首尾空格
                    int lastIndexOfWhitespace = fullName.lastIndexOf(" ");

                    if (lastIndexOfWhitespace != -1) { // 存在空格,可以分离
                        newStrArr[i * 2] = fullName.substring(0, lastIndexOfWhitespace); // 名字
                        newStrArr[i * 2 + 1] = fullName.substring(lastIndexOfWhitespace + 1); // 姓氏
                    } else { // 没有空格,整个作为名字,姓氏为空
                        newStrArr[i * 2] = fullName;
                        newStrArr[i * 2 + 1] = ""; // 或者设置为 null,取决于需求
                    }
                }
                return newStrArr;
            })
            .collect(Collectors.toCollection(ArrayList::new)); // 收集到新的 ArrayList<String[]>

        System.out.println("\n--- 分离后的作者姓名列表 (String[]) ---");
        for (String[] group : authorGroupsWithSeparatedNames) {
            System.out.println(Arrays.toString(group));
        }

        // 进一步优化:将分离后的姓名存储为 Author 对象列表
        List<Author> authorsList = authorGroups.stream()
            .flatMap(Arrays::stream) // 将 ArrayList<String[]> 展平为 Stream<String>
            .map(fullName -> {
                String trimmedFullName = fullName.trim();
                int lastIndexOfWhitespace = trimmedFullName.lastIndexOf(" ");
                String firstName;
                String surname;

                if (lastIndexOfWhitespace != -1) {
                    firstName = trimmedFullName.substring(0, lastIndexOfWhitespace);
                    surname = trimmedFullName.substring(lastIndexOfWhitespace + 1);
                } else {
                    firstName = trimmedFullName;
                    surname = ""; // 或 null
                }
                return new Author(firstName, surname);
            })
            .collect(Collectors.toList()); // 收集到 List<Author>

        System.out.println("\n--- 分离后的作者列表 (Author 对象) ---");
        for (Author author : authorsList) {
            System.out.println(author);
        }
    }
}

4. 结果验证

运行上述代码,我们将看到以下输出,验证了姓名已成功分离:

--- 原始作者姓名组列表 ---
[Christian Janze, Marten Risius]
[Kenan Xiao Auburn University, Ashish Gupta, Wenting Jiang, Xiao Qin]
[Kyuhan Lee, Sudha Ram]
[Kelvin King-Kizito]
[SingleName]

--- 分离后的作者姓名列表 (String[]) ---
[Christian, Janze, Marten, Risius]
[Kenan Xiao Auburn, University, Ashish, Gupta, Wenting, Jiang, Xiao, Qin]
[Kyuhan, Lee, Sudha, Ram]
[Kelvin, King-Kizito, , ]
[SingleName, ]

--- 分离后的作者列表 (Author 对象) ---
Author{name='Christian', surname='Janze'}
Author{name='Marten', surname='Risius'}
Author{name='Kenan Xiao Auburn', surname='University'}
Author{name='Ashish', surname='Gupta'}
Author{name='Wenting', surname='Jiang'}
Author{name='Xiao', surname='Qin'}
Author{name='Kyuhan', surname='Lee'}
Author{name='Sudha', surname='Ram'}
Author{name='Kelvin', surname='King-Kizito'}
Author{name='SingleName', surname=''}

从输出可以看出,每个全名字符串都根据最后一个空格被成功拆分。对于 "SingleName" 这样的单字姓名,名字部分是 "SingleName",姓氏部分留空。

5. 进阶:使用Author对象存储解析结果

在实际应用中,将解析后的名字和姓氏存储为独立的 Author 对象(如问题描述中提供的类)通常是更好的实践。这不仅使数据结构更清晰,也更符合面向对象的设计原则。

在上面的完整代码示例中,我们展示了两种收集方式:

  1. ArrayList:将每个作者组的姓名分离后,仍然保持原始的 String[] 结构,但每个 String[] 中的元素数量翻倍,交替存储名字和姓氏。
  2. List:通过 flatMap 将所有作者的全名展平,然后 map 到 Author 对象,最终得到一个包含所有 Author 对象的扁平列表。这种方式更推荐,因为它直接将数据映射到业务实体。

6. 注意事项与健壮性考虑

在进行姓名解析时,需要考虑一些边缘情况和潜在问题,以提高代码的健壮性:

  • 没有空格的姓名:如果姓名字符串中不包含空格(例如 "SingleName"),lastIndexOf(" ") 将返回 -1。此时,我们需要决定如何处理姓氏(例如,将其留空或将整个字符串作为名字)。上述代码已包含此处理。
  • 多余的空格:姓名字符串可能包含前导、尾随或内部多余的空格(例如 " Christian Janze " 或 "Christian Janze")。使用 trim() 方法可以在处理前清除这些多余的空格,确保解析的准确性。
  • 复杂姓名结构
    • 连字符姓氏:如 "Anna Müller-Schmidt"。如果我们的规则是最后一个单词是姓氏,那么 "Müller-Schmidt" 将被正确识别为姓氏。
    • 多个中间名:如 "John David Smith"。根据我们的规则,"John David" 将被视为名字,"Smith" 为姓氏。如果需要更精细的中间名分离,则需要更复杂的解析逻辑,可能涉及正则表达式或更高级的自然语言处理技术。
  • 空字符串或null:输入数据中可能存在空字符串或 null。在 map 操作中应添加 null 检查或空字符串处理,以避免 NullPointerException。

7. 总结

本文详细介绍了如何利用Java Stream API高效地从 ArrayList 中解析并分离作者的全名。我们通过 lastIndexOf(" ") 和 substring() 方法实现了名字和姓氏的精确提取,并展示了两种结果存储方式:ArrayList 和更推荐的 List。通过将数据映射到自定义的 Author 对象,我们不仅提升了代码的清晰度和可维护性,也为后续的业务逻辑处理奠定了良好的基础。在实际开发中,务必考虑各种姓名格式的复杂性,并根据需求选择最合适的解析策略和错误处理机制。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

258

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

766

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

219

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

356

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

244

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

547

2023.12.06

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.4万人学习

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

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