1. 概述

在这个教程中,我们将学习如何使用Scanner类的useDelimiter方法。

2. java.util.Scanner简介

ScannerAPI提供了一个简单的文本扫描器。默认情况下,Scanner会将输入分割成令牌,使用空格作为分隔符。让我们编写一个函数,它将:

  • 将输入传递给Scanner
  • 遍历Scanner,将令牌收集到一个列表中

让我们看看基本实现:

public static List<String> baseScanner(String input) {
    try (Scanner scan = new Scanner(input)) {
        List<String> result = new ArrayList<String>();
        scan.forEachRemaining(result::add);
        return result;
    }
}

请注意,在这段代码中,我们使用了try-with-resources来创建Scanner。这是因为Scanner类实现了AutoCloseable接口,这使得自动关闭资源成为可能。在Java 7之前,我们不能使用try-with-resources,因此需要手动处理。

我们还可以注意到,为了遍历Scanner元素,我们使用了forEachRemaining方法。这个方法是Java 8引入的。Scanner实现了Iterator,如果我们使用较旧的Java版本,就需要利用这个特性来遍历元素。

正如我们所说,Scanner默认使用空格解析输入。例如,调用baseScanner方法,输入为"Welcome to Baeldung",应该返回包含以下有序元素的列表:"Welcome", "to", "Baeldung"。

让我们编写一个测试来检查我们的方法是否按预期工作:

@Test
void whenBaseScanner_ThenWhitespacesAreUsedAsDelimiters() {
    assertEquals(List.of("Welcome", "to", "Baeldung"), baseScanner("Welcome to Baeldung"));
}

3. 使用自定义分隔符

现在,让我们设置Scanner使用自定义分隔符。我们将传递一个字符串,Scanner将使用它来拆分输入。

让我们看看如何做到这一点:

public static List<String> scannerWithDelimiter(String input, String delimiter) {
    try (Scanner scan = new Scanner(input)) {
        scan.useDelimiter(delimiter); 
        List<String> result = new ArrayList<String>();
        scan.forEachRemaining(result::add);
        return result;
    }
}

让我们讨论一些示例:

  • 我们可以使用单个字符作为分隔符:如果需要,字符需要转义。例如,如果我们想模仿基础行为,使用空格作为分隔符,我们将使用"\s"
  • 我们可以使用任何单词/短语作为分隔符
  • 我们可以使用多个可能的字符作为分隔符:为此,我们需要用|将它们分开。例如,如果我们想要在每个空格和换行符之间分割输入,我们将使用分隔符:"\n|\s"
  • 总之,我们可以使用任何正则表达式作为分隔符:例如,"a+"是一个有效的分隔符

让我们看看如何测试第一个案例:

@Test
void givenSimpleCharacterDelimiter_whenScannerWithDelimiter_ThenInputIsCorrectlyParsed() {
    assertEquals(List.of("Welcome", "to", "Baeldung"), scannerWithDelimiter("Welcome to Baeldung", "\\s"));
}

实际上,useDelimiter方法会在幕后将输入转换为一个封装在Pattern对象中的正则表达式。另一种选择是自己处理Pattern的实例化。为此,我们需要使用重写的方法useDelimiter(Pattern pattern),如下面所示:

public static List<String> scannerWithDelimiterUsingPattern(String input, Pattern delimiter) {
    try (Scanner scan = new Scanner(input)) {
        scan.useDelimiter(delimiter); 
        List<String> result = new ArrayList<String>();
        scan.forEachRemaining(result::add);
        return result;
    }
}

要实例化Pattern,我们可以使用compile方法,如下所示的测试:

@Test
void givenStringDelimiter_whenScannerWithDelimiterUsingPattern_ThenInputIsCorrectlyParsed() {
    assertEquals(List.of("Welcome", "to", "Baeldung"), DelimiterDemo.scannerWithDelimiterUsingPattern("Welcome to Baeldung", Pattern.compile("\\s")));
}

4. 总结

在这篇文章中,我们展示了一些可以用来调用useDelimiter函数的模式示例。我们注意到,默认情况下,Scanner使用空格分隔符,并指出我们可以在那里使用任何类型的正则表达式。

如往常一样,完整的代码可在GitHub上找到。