ZetCode

Java Pattern.splitAsStream 方法

上次修改时间:2025 年 4 月 20 日

splitAsStream 方法是 Java 的 java.util.regex.Pattern 类的一部分。它根据模式匹配拆分输入序列,并返回结果子字符串的流。此方法是在 Java 8 中引入的。

与返回数组的 split 不同,splitAsStream 返回一个 Stream<String>。这使得它非常适合对拆分结果进行函数式风格的处理。对于大型输入,该方法非常高效。

Basic splitAsStream 示例

此示例演示了 splitAsStream 的基本用法。我们将一个简单的逗号分隔字符串拆分成多个部分,并使用流操作处理它们。该模式匹配带有可选空格的逗号。

BasicSplitAsStream.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class BasicSplitAsStream {

    public static void main(String[] args) {
        
        String input = "apple, orange, banana, grape";
        Pattern pattern = Pattern.compile("\\s*,\\s*");
        
        Stream<String> fruitStream = pattern.splitAsStream(input);
        fruitStream.forEach(System.out::println);
    }
}

该代码在每个逗号处拆分输入字符串,忽略周围的空格。生成的流包含四个元素:“apple”、“orange”、“banana”和“grape”。我们使用 forEach 打印每个元素。

过滤拆分结果

此示例显示了如何过滤 splitAsStream 的结果。我们拆分包含数字的字符串并过滤掉非数字值。流 API 使此操作简洁明了。

FilterSplitResults.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class FilterSplitResults {

    public static void main(String[] args) {
        
        String input = "10, 20, thirty, 40, fifty, 60";
        Pattern pattern = Pattern.compile("\\s*,\\s*");
        
        pattern.splitAsStream(input)
            .filter(s -> s.matches("\\d+"))
            .map(Integer::parseInt)
            .forEach(System.out::println);
    }
}

该代码拆分输入并过滤以仅保留数字字符串。matches 检查确保我们仅处理数字。然后,我们将有效数字转换为整数并打印它们。

处理 CSV 数据

此示例演示了如何使用 splitAsStream 处理 CSV 数据。我们处理带引号的值和引号内的逗号。该模式考虑了 CSV 格式中的这些特殊情况。

CsvProcessing.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class CsvProcessing {

    public static void main(String[] args) {
        
        String input = "\"John, Doe\",25,\"New York, NY\",Developer";
        Pattern pattern = Pattern.compile(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
        
        pattern.splitAsStream(input)
            .map(s -> s.replaceAll("^\"|\"$", ""))
            .forEach(System.out::println);
    }
}

该模式使用正向预测来处理引号内的逗号。拆分后,我们从每个字段中删除周围的引号。这种方法可以正确处理“John, Doe”和“New York, NY”值。

多行输入处理

此示例显示了如何使用 splitAsStream 处理多行输入。我们将文本拆分为由空行分隔的段落。该模式匹配一个或多个换行符。

MultilineProcessing.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class MultilineProcessing {

    public static void main(String[] args) {
        
        String input = "First paragraph\n\nSecond paragraph\n\n\nThird paragraph";
        Pattern pattern = Pattern.compile("\\n+");
        
        pattern.splitAsStream(input)
            .filter(p -> !p.isEmpty())
            .forEach(p -> System.out.println("Paragraph:\n" + p + "\n"));
    }
}

该代码在换行符序列处拆分输入。我们过滤掉可能由前导或尾随换行符产生的空字符串。然后,用标签打印每个非空段落。

使用 splitAsStream 进行单词拆分

此示例演示了如何使用 splitAsStream 将文本拆分为单词。该模式匹配任何非单词字符序列。我们使用各种流操作处理这些单词。

WordSplitting.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class WordSplitting {

    public static void main(String[] args) {
        
        String input = "The quick brown fox jumps over the lazy dog";
        Pattern pattern = Pattern.compile("\\W+");
        
        pattern.splitAsStream(input)
            .map(String::toLowerCase)
            .distinct()
            .sorted()
            .forEach(System.out::println);
    }
}

该代码在非单词字符序列处将输入拆分为单词。我们将单词转换为小写,使用 distinct 删除重复项,对其进行排序并打印。这展示了将 splitAsStream 与流相结合的强大功能。

处理日志文件

此示例演示了如何使用 splitAsStream 处理日志文件条目。我们将日志字符串拆分为单个日志条目。然后解析每个条目以获取特定信息。

LogProcessing.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class LogProcessing {

    public static void main(String[] args) {
        
        String logs = "[INFO] User logged in\n" +
                     "[ERROR] Database connection failed\n" +
                     "[WARN] Disk space low\n" +
                     "[INFO] User logged out";
        
        Pattern pattern = Pattern.compile("\\n");
        
        pattern.splitAsStream(logs)
            .filter(entry -> entry.startsWith("[ERROR]"))
            .forEach(System.out::println);
    }
}

该代码在换行符处拆分日志字符串。我们过滤以仅保留错误条目并打印它们。这种方法对于将大型日志文件作为流进行处理非常有效。

使用 Lookarounds 进行复杂拆分

此示例显示了使用前瞻和后顾的高级拆分。我们在数字和字母之间的位置拆分字符串。这演示了复杂的拆分场景。

ComplexSplitting.java
package com.zetcode;

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class ComplexSplitting {

    public static void main(String[] args) {
        
        String input = "ABC123DEF456GHI789";
        Pattern pattern = Pattern.compile("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)");
        
        pattern.splitAsStream(input)
            .forEach(System.out::println);
    }
}

该模式使用后顾和前瞻断言来在数字和非数字字符之间进行拆分。结果是字母和数字交替序列的流。此技术对于解析复杂格式非常有用。

来源

Java Pattern.splitAsStream 文档

splitAsStream 方法提供了一种使用 Java 的流 API 处理拆分结果的强大方法。它对于大型输入和函数式风格的处理管道特别有用。

作者

我叫 Jan Bodnar,是一名经验丰富的程序员。 我于 2007 年开始撰写编程文章,至今已撰写了 1,400 多篇文章和八本电子书。 凭借超过八年的教学经验,我致力于分享我的知识并帮助其他人掌握编程概念。

列出所有Java教程