函数式风格java.util.regex提取match/group

Functional style java.util.regex match/group extraction

使用 java.util.regex 提取子字符串我发现自己在调用 :

时实现了相同的代码模式
Pattern p = Pattern.compile(pattern); // can be static final
Matcher m = p.matcher(input);
if (m.find()) { // or m.matches()
    foo(m.group(x));
} else {
    ...
}

是否有功能扩展或流行的库(guava / apache commons)可以避免丑陋的不必要且容易出错的局部变量,例如:

Pattern p = Pattern.compile(pattern); // can be static final
p.matchedGroup(input, x) // return Optional<String>
    .map(group -> foo(group))
    .orElse(...);

还有一系列匹配结果,例如:

Pattern p = Pattern.compile(pattern);
p.findMatches(input)
    .map((MatchResult mr) -> {
        mr.groupsIfPresent(x).map(g -> foo(g)).orElse(...)
    })
    .findFirst();

似乎 Java8 中唯一的功能添加是 .splitAsStream(),但这仅在尝试围绕匹配进行拆分时才有帮助。

有一个适用于 Stream<String>Optional<String> 的优雅解决方案:

Pattern pattern = Pattern.compile("...");

List<String> input = new ArrayList<>();

List<String> matches = input.stream()
        .map(pattern::matcher)
        .filter(Matcher::find)
        .map(m -> m.group(x))
        .collect(Collectors.toList());

虽然我想指出在 filter 调用中执行 modifying/mutating 操作是不寻常的。在 filter 调用中进行变异操作时请小心,并尽可能避免它们。对于这种情况,(从我的主观观点来看)这很好,因为您修改了刚刚在流中创建的对象,该对象未在流操作之外使用。

当你只有一个输入时使用Optional.ofNullable/of,其他一切看起来都一样。

以下内容仅来自

您可能正在寻找 Matcher::results,它会产生 Stream<MatchResult>

您可以通过以下方式使用,例如

p.matcher(input)
 .results()
 .map(MatchResult::group)
 .findAny()
 .orElse(null);

Holger 添加的一个有趣的内容是,在阅读 File 并寻找直接使用 Scanner::findAll 的模式以避免使用 File::lines

将整个文件加载到内存中