【问题标题】:Functional style java.util.regex match/group extraction函数式 java.util.regex 匹配/组提取
【发布时间】:2019-06-09 01:11:45
【问题描述】:

使用 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(),但这仅在尝试拆分匹配项时才有帮助。

【问题讨论】:

    标签: java regex java-9


    【解决方案1】:

    以下内容仅来自

    您可能正在寻找产生Stream&lt;MatchResult&gt;Matcher::results

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

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

    Holger 添加的一个有趣的补充是,在读取File 并寻找直接使用Scanner::findAll 的模式以避免使用@987654327 将整个文件加载到内存中@

    【讨论】:

    • 啊,仅限 Java9+。我还在使用 Java8
    • 如果你可以用变量 p 开始代码,比如p.matcher(input).results()...
    • 还值得注意的是添加了Scanner.findAll​(Pattern),因为人们经常以Files.lines()开头,然后搜索行字符串,例如使用flatMap,而不是首先流式传输比赛。
    【解决方案2】:

    有一个优雅的解决方案适用于Stream&lt;String&gt;Optional&lt;String&gt;

    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-call 中进行修改/变异操作是不寻常的。在filtercalls 中进行变异操作时请小心,并尽可能避免它们。在这种情况下(从我的主观观点来看)这很好,因为您修改了刚刚在流中创建的未在流操作之外使用的对象。

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

    【讨论】:

    • 也很高兴提及如何多次调用 find() 以涵盖所有出现的情况。使用 Java9 takeWhile 可能也更容易
    • 赞成,因为它适用于 java8,但接受 java9 答案作为未来的方式。
    • 那个例子中的 x 实际上是什么?
    • 检查PatternMatcher 的JavaDoc:group(0) 是整个匹配项,group(1) 是模式中第一个匹配的括号对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 2019-06-26
    相关资源
    最近更新 更多