1. 引言

在处理名称时,将它们缩短为每个单词首字母组成的缩写字符串可能会很有用。在这个教程中,我们将探讨在Java中实现这个功能的不同方法。

2. 假设

在创建缩写时,我们只考虑以字母开头的单词。其他任何单词都会被排除在外。此外,缩写可能会得到一个空字符串,没有任何有效的单词。另外,我们将整个字符串转换为大写。

3. 使用循环

我们可以通过空格分割文本,然后使用for循环遍历每个单词。接着,我们可以获取每个有效单词的首字符,并构建缩写:

String getInitialUsingLoop(String name) {
    if (name == null || name.isEmpty()) {
        return "";
    }
    String[] parts = name.split("\\s+");
    StringBuilder initials = new StringBuilder();
    for (String part : parts) {
        if (part.matches("[a-zA-Z].*")) {
            initials.append(part.charAt(0));
        }
    }
    return initials.toString().toUpperCase();
}

在这段代码中,我们使用正则表达式检查一个单词是否以字母开头,然后提取第一个字符来形成缩写。

我们可以编写一个单元测试,使用JUnit检查不同的情况:

@ParameterizedTest
@CsvSource({"John F Kennedy,JFK", ",''", "'',''", "Not Correct   88text,NC", "michael jackson,MJ", "123,''", "123 234A,''", "1test 2test, ''"})
void getInitialFromName_usingLoop(String input, String expected) {
    String initial = getInitialUsingLoop(input);
    assertEquals(expected, initial);
}

在上述测试用例中,我们利用了JUnit的参数化测试特性,指定多个输入和预期输出组合。这样,我们可以在不同条件下确保功能的全面覆盖和验证。

4. 使用StringTokenizer

我们可以使用StringTokenizer将文本分割成单词。让我们看看实现方式:

String getInitialUsingStringTokenizer(String name) 
    if (name == null || name.isEmpty()) {
        return "";
    }
    StringTokenizer tokenizer = new StringTokenizer(name);
    StringBuilder initials = new StringBuilder();
    while (tokenizer.hasMoreTokens()) {
        String part = tokenizer.nextToken();
        if (part.matches("[a-zA-Z].*")) {
            initials.append(part.charAt(0));
        }
    }
    return initials.toString().toUpperCase();
}

这段代码与之前的实现类似,只是使用了StringTokenizer而不是split()方法。然而,StringTokenizer是出于兼容性原因保留的一个过时类,我们应该考虑使用split()方法。

对于这个方法,我们可以使用相同的参数化测试。

5. 使用正则表达式

另一种实现此功能的方法是使用正则表达式。我们可以通过使用正则表达式匹配来捕获每个有效单词的首字符

String getInitialUsingRegex(String name) {
    if (name == null || name.isEmpty()) {
        return "";
    }
    Pattern pattern = Pattern.compile("\\b[a-zA-Z]");
    Matcher matcher = pattern.matcher(name);
    StringBuilder initials = new StringBuilder();
    while (matcher.find()) {
        initials.append(matcher.group());
    }
    return initials.toString().toUpperCase();
}

同样,我们可以创建一个测试用例来验证实现。

6. 使用流API

我们还可以使用基于函数式编程的流API,自Java 8以来就已可用。现在,让我们深入了解一下实现:

String getInitialUsingStreamsAPI(String name) {
    if (name == null || name.isEmpty()) {
        return "";
    }
    return Arrays.stream(name.split("\\s+"))
      .filter(part -> part.matches("[a-zA-Z].*"))
      .map(part -> part.substring(0, 1))
      .collect(Collectors.joining())
      .toUpperCase();
}

在这种情况下,我们结合了filter(), map(), 和 collect() 方法来达成目标。我们也可以使用类似的参数化测试来验证这个实现。

7. 总结

本文讨论了在Java中从名字中提取首字母的不同方法,这些方法同样可以用于生成任何文本的缩写,而不仅仅是名字。此外,我们探讨了传统的基于循环的方法、正则表达式以及更函数式编程的方式来实现相同的结果。根据具体场景,开发人员可以选择最适合他们需求的方法。

如往常一样,本教程中使用的示例代码可在GitHub上找到。