有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用流替换java正则表达式

好奇的是,有没有一种方法可以用Java流来编写呢

private final static Pattern decodePattern = Pattern.compile("&#(\\d+);");

StringBuffer buf = new StringBuffer();

Matcher m = decodePattern.matcher(somestring);
while (m.find()) {
    m.appendReplacement(buf, String.valueOf((char) Integer.parseInt(m.group(1))));
}
m.appendTail(buf);

String decodeString = buf.toString();

共 (1) 个答案

  1. # 1 楼答案

    Java 9

    可以使用Java 9方法中的重载从Matcher类:
    实现更干净的代码 ^{}。基本上,我们现在可以替换如下代码

    StringBuffer sb = new StringBuffer();
    while(matcher.find()){
        matcher.appendReplacement(sb, /*create replacement*/);
    }
    matcher.appendTail(sb);
    String result = sb.toString;
    

    String replaced = matcher.replaceAll(match -> /*create replacement*/);
    

    比如说

    String replaced = Pattern.compile("\\b\\w")
                             .matcher("foo bar baz")
                             .replaceAll(match -> match.group().toUpperCase());
    //replaced: "Foo Bar Baz"
    

    还添加了对元素流匹配模式的支持:^{},但在我看来,您的循环并不是流的好候选。即使使用results(),您的代码也会如下所示:

    //BTW Java 9 provides support for StringBuilder beside StringBuffer 
    //for appendReplacement/appendTail
    
    Matcher matcher = ...
    StringBuilder buf = new StringBuilder(); 
    
    matcher.results()
           .map(result -> String.valueOf((char) Integer.parseInt(result.group(1))) )
           .forEach(replacement -> matcher.appendReplacement(buf, replacement));
    matcher.appendTail(buf);
    
    String decodeString = buf.toString();
    

    所以看起来没那么干净


    Java 8

    在Java8中,模式和匹配器类在流支持方面没有太大变化。只有Pattern收到了^{}方法,但它创建了元素流,其中Pattern表示要拆分的分隔符,而不是要查找的文本

    如果您想简化Java 8中的代码,请编写您自己的方法,在该方法中,您将提供Matcher和函数,该函数将匹配的内容(最好由MatchResult或Matcher表示,以便它可以访问group(...)方法)映射到应该放置的替换项

    这种方法可能看起来像:

    public static String replaceMatches(Matcher m, Function<MatchResult, String> mapping){
        
        StringBuffer sb = new StringBuffer();
        while(m.find()){
            MatchResult matchResult = m.toMatchResult();
            m.appendReplacement(sb, mapping.apply(matchResult));
        }
        m.appendTail(sb);
        
        return sb.toString();
    }
    

    你可以像这样使用它:

    Pattern p = Pattern.compile("\\b\\w");
    Matcher m = p.matcher("foo bar baz");
    
    String result = replaceMatches(m, mr -> mr.group().toUpperCase());
    
    System.out.println(result);
    

    结果:Foo Bar Baz