为什么是基于正则表达式在Java中最字符串操作?
在Java中,有一堆方法都与操作字符串有关。
最简单的例子是String.split(“something”)方法。 现在,许多这些方法的实际定义是它们都使用正则表达式作为它们的输入参数。这使所有非常强大的构建块。 现在在许多方法中你会看到两个效果: >每次调用该方法时,它们都会重新编译表达式。因此,它们施加了性能影响。 所以它不仅是默认方法是强大的,他们似乎对他们实际使用的功能强大。在内部,我们开发了一个“fastSplit”方法,拆分固定字符串。我在家里写了一个测试,看看我能做到多快,如果它是一个单一的字符。两者都明显快于“标准”分割方法。 所以我想知道:为什么是Java API选择现在的方式? 更新:我一起打了几个电话,看看分割字符串需要多长时间。 简短总结:这是一个很大的区别! 我对每个测试用例做10000000次迭代,总是使用输入 "aap,noot,mies,wim,zus,jet,teun" 并始终使用“,”或“”作为拆分参数。 这是我在我的Linux系统(它是一个Atom D510盒子,所以它有点慢): fastSplit STRING Test 1 : 11405 milliseconds: Split in several pieces Test 2 : 3018 milliseconds: Split in 2 pieces Test 3 : 4396 milliseconds: Split in 3 pieces homegrown fast splitter based on char Test 4 : 9076 milliseconds: Split in several pieces Test 5 : 2024 milliseconds: Split in 2 pieces Test 6 : 2924 milliseconds: Split in 3 pieces homegrown splitter based on char that always splits in 2 pieces Test 7 : 1230 milliseconds: Split in 2 pieces String.split(regex) Test 8 : 32913 milliseconds: Split in several pieces Test 9 : 30072 milliseconds: Split in 2 pieces Test 10 : 31278 milliseconds: Split in 3 pieces String.split(regex) using precompiled Pattern Test 11 : 26138 milliseconds: Split in several pieces Test 12 : 23612 milliseconds: Split in 2 pieces Test 13 : 24654 milliseconds: Split in 3 pieces StringTokenizer Test 14 : 27616 milliseconds: Split in several pieces Test 15 : 28121 milliseconds: Split in 2 pieces Test 16 : 27739 milliseconds: Split in 3 pieces 正如你可以看到的,如果你有很多“固定字符”拆分做一个很大的不同。 给你们一些洞察力;我目前在Apache日志文件和Hadoop竞技场与一个大网站的数据。所以对我这个东西真的很重要:) 我在这里没有考虑的东西是垃圾收集器。至于我可以告诉编译正则表达式到一个Pattern / Matcher / ..将分配很多对象,需要收集一些时间。所以也许从长远来看,这些版本之间的差异甚至更大….或更小。 我到目前为止的结论: >只有优化这,如果你有很多字符串来拆分。 P.S。我给你所有我自己的分裂的char方法来玩(在许可证下,这个网站上的一切都在:))。我从来没有完全测试他们..玩的开心。 private static String[] stringSplitChar(final String input,final char separator) { int pieces = 0; // First we count how many pieces we will need to store ( = separators + 1 ) int position = 0; do { pieces++; position = input.indexOf(separator,position + 1); } while (position != -1); // Then we allocate memory final String[] result = new String[pieces]; // And start cutting and copying the pieces. int previousposition = 0; int currentposition = input.indexOf(separator); int piece = 0; final int lastpiece = pieces - 1; while (piece < lastpiece) { result[piece++] = input.substring(previousposition,currentposition); previousposition = currentposition + 1; currentposition = input.indexOf(separator,previousposition); } result[piece] = input.substring(previousposition); return result; } private static String[] stringSplitChar(final String input,final char separator,final int maxpieces) { if (maxpieces <= 0) { return stringSplitChar(input,separator); } int pieces = maxpieces; // Then we allocate memory final String[] result = new String[pieces]; // And start cutting and copying the pieces. int previousposition = 0; int currentposition = input.indexOf(separator); int piece = 0; final int lastpiece = pieces - 1; while (currentposition != -1 && piece < lastpiece) { result[piece++] = input.substring(previousposition,previousposition); } result[piece] = input.substring(previousposition); // All remaining array elements are uninitialized and assumed to be null return result; } private static String[] stringChop(final String input,final char separator) { String[] result; // Find the separator. final int separatorIndex = input.indexOf(separator); if (separatorIndex == -1) { result = new String[1]; result[0] = input; } else { result = new String[2]; result[0] = input.substring(0,separatorIndex); result[1] = input.substring(separatorIndex + 1); } return result; }
注意,正则表达式不需要每次都重新编译。从
Javadoc:
Pattern.compile(regex).split(str,n) 也就是说,如果你担心性能,你可以预编译模式,然后重用它: Pattern p = Pattern.compile(regex); ... String[] tokens1 = p.split(str1); String[] tokens2 = p.split(str2); ... 代替 String[] tokens1 = str1.split(regex); String[] tokens2 = str2.split(regex); ... 我相信这个API设计的主要原因是方便。由于正则表达式包括所有“固定”字符串/字符,它简化了API有一个方法,而不是几个。如果有人担心性能,正则表达式仍然可以如上所示预编译。 我的感觉(我不能回来与任何统计证据)是大多数情况下String.split()用于上下文中的性能不是一个问题。例如。它是一次性的行为,或者性能差异与其他因素相比是可以忽略的。 IMO很少是这样的情况,你在紧缩循环中使用相同的正则表达式数千次拆分字符串,其中性能优化确实有意义。 有趣的是看到一个正则表达式匹配器实现与固定字符串/字符的性能比较与专门的匹配器的性能比较。差异可能不够大,不足以证明单独实现。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |