Pattern.asPredicate中的错误?

时间:2014-05-08 11:45:03

标签: java regex java-8

给出以下字符串列表:

List<String> progLangs = Arrays.asList("c#", "java", "python", "scala");

和一个应该匹配4个字母的小写字符串的正则表达式。

Pattern p = Pattern.compile("[a-z]{4}");

现在我想找到适合模式progLangs的{​​{1}}元素。

以旧的方式去做:

p

我得到了预期的结果:

for (String lang : progLangs) {
    if (p.matcher(lang).matches()) {
        System.out.println(lang);
    }
}

但是当我尝试使用Java 8流实现相同功能并使用Pattern.asPredicate将模式转换为谓词时:

java

结果是:

progLangs.stream()
    .filter(p.asPredicate())
    .forEach(System.out::println);

为什么会这样?看起来Patter.asPredicate产生一个接受部分匹配的谓词。 Pattern API中的等价物是什么? documentation仅表示:

  

创建一个可用于匹配字符串的谓词。

我希望它是典型的java python scala ,但它是其他的...如何解释这种不一致?

2 个答案:

答案 0 :(得分:11)

他们没有做同样的事情 - 谓词使用find rather than matches。等效的旧代码&#39;方式是:

for (String lang : progLangs) {
    if (p.matcher(lang).find()) {
        System.out.println(lang);
    }
}

在这种情况下,我会使用自己的谓词:

progLangs.stream()
    .filter(s -> p.matcher(s).matches())
    .forEach(System.out::println);

文档似乎确实有误导性。

答案 1 :(得分:1)

通过JDK/11,您可以使用新的 Pattern.asMatchPredicate API以单行代码的形式完成您最初尝试的操作:

progLangs.stream()
         .filter(p.asMatchPredicate()) // the matches predicate
         .forEach(System.out::println);

这是相同的javadoc读取的内容:

/**
 * Creates a predicate that tests if this pattern matches a given input string.
 *
 * @apiNote
 * This method creates a predicate that behaves as if it creates a matcher
 * from the input sequence and then calls matches, for example a
 * predicate of the form:
 *   s -> matcher(s).matches();
 *
 * @return  The predicate which can be used for matching an input string
 *          against this pattern.
 * @since   11
 * @see     Matcher#matches
 */
public Predicate<String> asMatchPredicate() {
    return s -> matcher(s).matches();
}