Pattern.split比String.split慢

Chr*_*ris 9 java regex string split

有两种方法:

private static void normalSplit(String base){
    base.split("\\.");
}

private static final Pattern p = Pattern.compile("\\.");

private static void patternSplit(String base){
    //use the static field above
    p.split(base);

}
Run Code Online (Sandbox Code Playgroud)

我在主方法中测试它们:

public static void main(String[] args) throws Exception{
    long start = System.currentTimeMillis();
    String longstr = "a.b.c.d.e.f.g.h.i.j";//use any long string you like
    for(int i=0;i<300000;i++){
        normalSplit(longstr);//switch to patternSplit to see the difference
    }
    System.out.println((System.currentTimeMillis()-start)/1000.0);
}
Run Code Online (Sandbox Code Playgroud)

直觉上,我认为String.split最终会Pattern.compile.split(在经过大量额外工作之后)做出真实的事情.我可以提前构造Pattern对象(它是线程安全的)并加速分裂.

但事实是,使用预先构建的Pattern 比直接调用要慢得多String.split.我在它们上尝试了一个长度为50个字符的字符串(使用MyEclipse),直接调用只消耗了使用预构建的Pattern对象的一半时间.

请有人能告诉我为什么会这样吗?

tob*_*s_k 5

这可能取决于Java的实际实现。我使用的OpenJDK 7,在这里,String.split确实调用Pattern.compile(regex).split(this, limit),但只有当该字符串分割的,regex是多单字符。

有关源代码,请参见此处,第2312行。

public String[] split(String regex, int limit) {
   /* fastpath if the regex is a
      (1)one-char String and this character is not one of the
         RegEx's meta characters ".$|()[{^?*+\\", or
      (2)two-char String and the first char is the backslash and
         the second is not the ascii digit or ascii letter.
   */
   char ch = 0;
   if (((regex.count == 1 &&
       // a bunch of other checks and lots of low-level code
       return list.subList(0, resultSize).toArray(result);
   }
   return Pattern.compile(regex).split(this, limit);
}
Run Code Online (Sandbox Code Playgroud)

当您按进行拆分时"\\.",它使用的是“快速路径”。也就是说,如果您使用的是OpenJDK。