String 的 split、subString,外加StringTokenizer之性能比较

被刻印的时光 ゝ 提交于 2019-12-22 11:13:20

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

最近在阅读java.lang下的源码,读到String时,突然想起面试的时候曾经被人问过:都知道在大数据量情况下,使用String的split截取字符串效率很低,有想过用其他的方法替代吗?用什么替代?我当时的回答很斩钉截铁:没有。

google了一下,发现有2中替代方法,于是在这里我将对这三种方式进行测试。

测试的软件环境为:Windows XP、eclipse、JDK1.6。

测试用例使用类ip形式的字符串,即3位一组,使用”.”间隔。数据分别使用:5组、10组、100组、1000组、10000组、100000组。

实现

闲话不说,先上代码:

 1 package test.java.lang.ref;  2  3 import java.util.Random;  4 import java.util.StringTokenizer;  5  6 /**  7  * String测试类  8  * @author xiaori.Liu  9  * 10  */ 11 public class StringTest { 12     13     public static void main(String args[]){ 14         String orginStr = getOriginStr(10); 15         16         //////////////String.splic()表现////////////////////////////////////////////// 17         System.out.println("使用String.splic()的切分字符串"); 18         long st1 = System.nanoTime(); 19         String [] result = orginStr.split("\\."); 20         System.out.println("String.splic()截取字符串用时:" + (System.nanoTime()-st1)); 21         System.out.println("String.splic()截取字符串结果个数:" + result.length); 22         System.out.println(); 23         24         //////////////StringTokenizer表现////////////////////////////////////////////// 25         System.out.println("使用StringTokenizer的切分字符串"); 26         long st3 = System.nanoTime();  27         StringTokenizer token=new StringTokenizer(orginStr,".");  28         System.out.println("StringTokenizer截取字符串用时:"+(System.nanoTime()-st3)); 29         System.out.println("StringTokenizer截取字符串结果个数:" + token.countTokens()); 30         System.out.println(); 31         32         ////////////////////String.substring()表现////////////////////////////////////////// 33         34         35         long st5 = System.nanoTime();  36         int len = orginStr.lastIndexOf("."); 37         System.out.println("使用String.substring()切分字符串");  38         int k=,count=;  39         40         for (int i = ; i <= len; i++) {  41          if(orginStr.substring(i, i+1).equals(".")){  42           if(count==){  43            orginStr.substring(, i);  44           }else{  45              orginStr.substring(k+1, i); 46              if(i == len){ 47                orginStr.substring(len+1, orginStr.length()); 48            } 49           } 50           k=i;count++;  51          }  52         } 53         System.out.println("String.substring()截取字符串用时"+(System.nanoTime()-st5));  54         System.out.println("String.substring()截取字符串结果个数:" + (count + 1)); 55     } 56     57     /** 58      * 构造目标字符串 59      * eg:10.123.12.154.154 60      * @param len 目标字符串组数(每组由3个随机数组成) 61      * @return 62      */ 63     private static String getOriginStr(int len){ 64         65         StringBuffer sb = new StringBuffer(); 66         StringBuffer result = new StringBuffer(); 67         Random random = new Random(); 68         for(int i = ; i < len; i++){ 69             sb.append(random.nextInt(9)).append(random.nextInt(9)).append(random.nextInt(9)); 70             result.append(sb.toString()); 71             sb.delete(, sb.length()); 72             if(i != len-1) 73                 result.append("."); 74         } 75         76         return result.toString(); 77     } 78 } 

改变目标数据长度修改getOriginStr的len参数即可。

5组测试数据结果如下图:

下面这张图对比了下,split耗时为substring和StringTokenizer耗时的倍数:

好吧,我又花了点儿时间,做了几张图表来分析这3中方式的性能。

首先来一张柱状图对比一下这5组数据截取所花费的时间:

从上图可以看出StringTokenizer的性能实在是太好了(对比另两种),几乎在图表中看不见它的身影。遥遥领先。substring花费的时间始终比split要少,但是耗时也在随着数据量的增加而增加。

下面3张折线图可以很明显看出split、substring、StringTokenizer3中实现随着数据量增加,耗时的趋势。

split是变化最大的,也就是数据量越大,截取所需要的时间增长越快。

substring则比split要平稳一点点,但是也在增长。

StringTokenizer则是表现最优秀的,基本上平稳,始终保持在5000ns一下。

结论

最终,StringTokenizer在截取字符串中效率最高,不论数据量大小,几乎持平。substring则要次之,数据量增加耗时也要随之增加。split则是表现最差劲的。

究其原因,split的实现方式是采用正则表达式实现,所以其性能会比较低。至于正则表达式为何低,还未去验证。split源码如下:

1 public String[] split(String regex, int limit) { 2     return Pattern.compile(regex).split(this, limit); 3 } 

验证可能存在不合理的地方,如哪里不合适,还请指出,共同进步。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!