Java Regex在拆分之前检查以前的char

时间:2011-01-11 05:04:05

标签: java regex

我有一个像这样的字符串

此:字符串:必须〜:是:分流:当:以前:炭:是:不〜:此

我需要用分隔符“:”拆分该行,但前提是分隔符前的字符不是“〜”

我现在有以下正则表达式:

String[] split = str.split(":(?<!~:)");

它有效,但由于我纯粹通过反复试验来达到它,我不相信它是最有效的方法。此外,此功能将经常在大字符串上重复调用,因此性能会受到考虑。什么是更有效的方法呢?

3 个答案:

答案 0 :(得分:5)

这是一个稍微简单的方法:

(?<!~):

这样你两次不匹配:。我怀疑你会看到表演上的任何差异。通过简单地查找下一个冒号并检查之前的波浪号,在没有正则表达式的情况下编写也非常简单。

答案 1 :(得分:2)

更新为了使这更公平,我想使用已编译的模式并查看结果。所以我更新了代码以使用编译模式,非编译模式和我的自定义方法。

虽然这不使用正则表达式,但它证明比正则表达式更快。<​​/ p>

public static void main(String[] args) {
    Pattern pattern = Pattern.compile(":(?<!~:)");
    for (int runs = 0; runs < 4; ++runs) {
        long start = System.currentTimeMillis();
        for (int index = 0; index < 100000; ++index) {
            "This:string:must~:be:split:when:previous:char:is:not~:this".split(":(?<!~:)");
        }
        long stop = System.currentTimeMillis();
        System.out.println("Run: " + runs + " Regex: " + (stop - start));

        start = System.currentTimeMillis();
        for (int index = 0; index < 100000; ++index) {
            pattern.split("This:string:must~:be:split:when:previous:char:is:not~:this");
        }
        stop = System.currentTimeMillis();
        System.out.println("Run: " + runs + " Compiled Regex: " + (stop - start));

        start = System.currentTimeMillis();
        for (int index = 0; index < 100000; ++index) {
            specialSplit("This:string:must~:be:split:when:previous:char:is:not~:this");
        }
        stop = System.currentTimeMillis();
        System.out.println("Run: " + runs + " Custom: " + (stop - start));
    }

    for (String s : specialSplit("This:string:must~:be:split:when:previous:char:is:not~:this")) {
        System.out.println(s);
    }
}

public static String[] specialSplit(String text) {
    List<String> stringsAfterSplit = new ArrayList<String>();

    StringBuilder splitString = new StringBuilder();
    char previousChar = 0;
    for (int index = 0; index < text.length(); ++index) {
        char charAtIndex = text.charAt(index);
        if (charAtIndex == ':' && previousChar != '~') {
             stringsAfterSplit.add(splitString.toString());
             splitString.delete(0, splitString.length());
        } else {
                splitString.append(charAtIndex);
        }
            previousChar = charAtIndex;
    }
    if (splitString.length() > 0) {
        stringsAfterSplit.add(splitString.toString());
    }
    return stringsAfterSplit.toArray(new String[stringsAfterSplit.size()]);
}

<强>输出

Run: 0 Regex: 468
Run: 0 Compiled Regex: 365
Run: 0 Custom: 169
Run: 1 Regex: 437
Run: 1 Compiled Regex: 363
Run: 1 Custom: 166
Run: 2 Regex: 445
Run: 2 Compiled Regex: 363
Run: 2 Custom: 167
Run: 3 Regex: 436
Run: 3 Compiled Regex: 361
Run: 3 Custom: 167
This
string
must~:be
split
when
previous
char
is
not~:this

答案 2 :(得分:0)

试试这个。 [^~]:

在JS中测试