java - 从给定位置提取小写子字符串的好方法?

标签 java string

我知道的一个是将 Matcher 应用于子字符串,另一个只是手动搜索第一个不是小写的字符。

那么有什么好的方法可以做到这一点?
对于如此简单的任务,使用 Matcher 似乎是一个巨大的杀伤力。

事实上,可以使用与 C++ find_first_not_of() 等效的方法,但 Java 的库中似乎没有这样的方法。

更新:

嗯,Matcher 的执行方式比手动执行慢 4-10 倍,不过,如果操作正确,则非常好且可读(请参阅 Andreas 的回答)。
然而,习惯了代码通常应该尽可能高效(保持可读性),我仍然有兴趣看看是否可以使用标准库和/或 native Java 技巧更快地完成同样的事情.

更新 2:

我发现了一个更快一点的惯用方法:stream API

目前发现的方法有:

// 1. Andreas' correction of the Matcher way
static String getLowercaseSubstringAt (final String s, final int pos) {
    Matcher m = Pattern.compile("^\\p{Ll}+").matcher(s).region(pos, s.length());
    return (m.find() ? m.group() : "");
}
// 2. The same with a static Pattern: 2.5 times faster
//    I thought the compiler would optimize it by default
//    Don't like the idea to make the Pattern external
static Pattern p = Pattern.compile("^\\p{Ll}+");
static String getLowercaseSubstringAt (final String s, final int pos) {
    Matcher m = p.matcher(s).region(pos, s.length());
    return (m.find() ? m.group() : "");
}
// 3. Stream API with a range of indices: 3x the speed of the first
//    Makes use of the Java way to say `find_first(_not)_of()`
static String getLowercaseSubstringAt (final String s, final int pos) {
    int idx = IntStream.range(pos, s.length())
             .filter(i -> !Character.isLowerCase(s.charAt(i)))
             .findFirst()
             .orElse(s.length());
    return s.substring(pos, idx);
}
// 4. Doing it manually. Relatively dirty, but fast. 10x the speed
static String getLowercaseSubstringAt (final String s, final int pos) {
    for (int i = pos; i < s.length(); i++)
        if (!Character.isLowerCase(s.charAt(i)))
            return s.substring(pos, i);
    return s.substring(pos);
}

Stream API 看起来是目前语言上的最佳选择:不需要外部资源,干净,相对较快。

最佳答案

不知道为什么你说 Matcher 方式确实浪费,无论是在代码上还是在时间上。

当然,正则表达式比简单的 for 循环慢,但除非您在紧密循环中重复执行此操作(1000 多次),否则您不会注意到差异。在您测量性能并发现问题之前,它可能不是问题。当心过早的优化。

但是代码浪费了?只是因为你做错了:

static String getLowercaseSubstringAt (final String s, final int pos) {
    Matcher m = Pattern.compile("^\\p{Ll}+").matcher(s).region(pos, s.length());
    return (m.find() ? m.group() : "");
}

由于您的非正则表达式使用 Character.isLowerCase() 进行完整小写检查,因此我也更新了正则表达式来执行此操作。

关于java - 从给定位置提取小写子字符串的好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43694875/

相关文章:

java - 从 int 中删除的方法

java - 替换字符串中的提及

java - droidtext 添加图像不起作用

java - 如何从同一文本字段获取两个值?

java - 如何从java中的ENUM中随机选择两个字符串之间的字符串?

java - java中的不可变字符串

javascript - 如何选择数组的前三个元素并构造一个逗号分隔的字符串

php - 如何从 PHP 中的文本字符串中替换多个项目?

java.util.logging:如何抑制日期线

java - 如何制作以某种方式重复参数方法的java方法?