0

我需要选择两个外括号之间的所有文本。由于不能保证正则表达式选择匹配的括号,我编写了以下代码:

public static String getContentBetweenCorresponding(String s, char left, char right) {
    int pos = s.indexOf(left);
    if ( pos > -1 ) {
        int start = pos;
        int openCount = 0;
        while ( pos < s.length() ) {
            char currentChar = s.charAt(pos);
            if ( currentChar == right ) {
                if ( openCount > 1 ) // if openCount == 1 then correct one 
                    openCount--;
                else
                    return s.substring(start + 1, pos);
            } else if ( currentChar == left )
                openCount++;
            pos++;
        }
    }
    return null;
}

有用。然而它非常慢。我怎样才能加快速度?此方法需要 5s 处理手头的字符串,是我的应用程序的瓶颈。

提前非常感谢!

编辑:我想要做的是获取匹配括号之间的文本。

getContentBetweenCorresponding("bla{{{blubb}}}}}}", '{', '}')

应该返回

"{{blubb}}"
4

3 回答 3

2

您编写的方法没有任何明显的低效率。我的猜测是问题实际上在于以下之一:

  1. 您可能会为同一个 string 多次调用此函数s,而您可以调用一次并存储结果。
  2. 您可能将非常大的字符串传递给此方法,字符串开头和右大括号之间的距离非常大。

{如果和之间的距离}对于您的实际输入来说预计很大,您可以重写indexOf用于直接查找的方法left,而right不是测试charAt每个字符的 。在这种情况下,对 的调用indexOf将比对 的调用少得多charAt,虽然最外面的大括号之间的字符串中的字符将被检查至少两次,但内部实现的indexOf性能可能会超过 JIT 正在使用的性能charAt

于 2013-06-17T00:10:50.437 回答
1

那看起来还不错。您确定是这种方法导致了性能问题吗?

你可以尝试一个紧密的循环,只是为了找到下一个打开、关闭或结束。也许转换为 char 数组而不是使用charAttoCharArray或者可能更好getChars)。至少在过去,你会用更小的方法获得更好的结果。

在最近的 Java 版本中,substring将复制支持数组,这在过去是不会发生的。

所以这就是我如何在不进行任何基准测试(!)的情况下为性能编写它(可能可以修改接口以不创建一个String,甚至不采用一个) -

public static String betweenMatchedBrackets(
     String str, char open, char close
) {
    int start = str.indexOf(open);
    if (start == -1) {
        return null;
    }

    ++start;
    int strLen = str.length();
    char[] cs = new char[strLen-start]; // Assume typically much of string
    strLen.getChars(start, len, cs, 0);

    int foundLen = endingBracket(cs, open, closed);
    return foundLen != cs.length ? str.substring(start, start+foundLen) : null;
}
private static int endingBracket(char cs, char open, char closed) {
    int depth = 1;
    int i = 0;
    for (; depth != 0 && i != cs.length; ) {
        i = nextInteresting(cs, i, open, close);
        if (i != cs.length) {
            char c = cs[i];
            depth += c==open ? 1 : -1;
        }
    }
    return int;
}
private static int nextInteresting(char[] cs, int off, char open, char close) {
    for (; off != cs.length && cs[off] != open && cs[off] != close; ++off) {
    }
    return off;
}

(未进行基准测试或编译。)

于 2013-06-17T00:08:09.253 回答
-2

我认为您不需要编写自己的方法。您可以使用 Java 正则表达式来获取括在括号中的字符串。下面的示例代码将在普通括号中间为您提供字符串

    String str = "Hello (big) world";
    Pattern pattern = Pattern.compile("\\((\\w+)\\)");
    Matcher matcher = pattern.matcher(str);
    matcher.find();

            // result below is "big"
    String result = matcher.group(1);
于 2013-06-17T00:07:37.103 回答