簡體   English   中英

在Java中匹配外括號太慢

[英]Match outer brackets in Java too slow

我需要選擇兩個外括號之間的所有文本。 由於不能確保使用正則表達式選擇匹配的括號,因此我編寫了以下代碼:

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}}"

您編寫的方法沒有任何明顯的低效率。 我的猜測是問題實際上出在以下其中一項:

  1. 當您一次調用它並存儲結果時,您可能為同一個字符串s多次調用此函數。
  2. 您可能正在將非常大的字符串傳遞給此方法,並且字符串的開頭和右括號之間的距離非常大。

如果之間的距離{}預期為大,你的實際投入 ,你可以重寫方法使用indexOf直接找到leftright ,而不是測試charAt每個字符。 在這種情況下,對indexOf調用要比對charAt調用少很多,而對最外花括號之間的字符串中的字符進行的檢查至少要兩倍於indexOf的內部實現,才可能超過JIT所做的性能。 charAt

看起來還不錯。 您確定是這種方法導致了性能問題嗎?

您可以嘗試緊密循環,以查找下一個打開,關閉或結束。 也許轉換為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;
}

(未進行基准測試或編譯。)

我認為您不需要編寫自己的方法。 您可以使用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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM