博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于java字符串常用一些api 效率比拼小结(java对大型的字符串api处理效率比拼)...
阅读量:6915 次
发布时间:2019-06-27

本文共 3704 字,大约阅读时间需要 12 分钟。

hot3.png

比如说我们要处理几十万个的字符串的处理,可能比如字符串的正则替换,比如replace、replaceAll,字符串的拼接或添加使用 +,StringBuilder的append,字符串的分割使用split。然而往往如果我们的数据量很小的时候,其实看不出来有任何的问题。下面我们来看看他们的底层做了些什么

1、我们先来看replace和replaceAll,根据api,replace是不支持正则表达式,replaceAll是支持正则表达式的。

下面看下replaceAll底层实现,由于篇幅关系,只贴部分的主要代码

public String replaceAll(String regex, String replacement) {    return Pattern.compile(regex).matcher(this).replaceAll(replacement);}
public String replaceAll(String replacement) {    reset();    boolean result = find(); //这儿主要是遍历看是否有匹配的第一个字符,如果没有直接返回,如果整个字符串没有字符就直接return了    if (result) {        StringBuffer sb = new StringBuffer();        do {            appendReplacement(sb, replacement);//有的话对第一次find的字符进行添加            result = find();//继续寻找,一直寻找到末尾的时候没有了就直接跳出do循环        } while (result);        appendTail(sb);        return sb.toString();    }    return text.toString();}

所以replaceAll是遍历两次

String.replace  主要由两个函数,它不支持正则替换,

replace(CharSequence target, CharSequence replacement)//字符替换,比如“abc”一串的字符替换一个“a”,从匹配是否是“abc”来说,和下面字符替换肯定计算更多一些的,具体的不贴代码了,比较冗长。
replace(char oldChar, char newChar)//字符串替换,一般来说替换单个字符,使用它,效率高,同样的替换replace("a","b") 和替换replace('a','b')过程是不一样的,后面的效率高。
public String replace(char oldChar, char newChar) {    if (oldChar != newChar) {//如果相等就直接返回了喔        int len = value.length;        int i = -1;        char[] val = value; /* avoid getfield opcode */        while (++i < len) {            if (val[i] == oldChar) {// i值 定位到第一个字符,利于下面缩减替换的区间                break;            }        }        if (i < len) {            char buf[] = new char[len];//创建char数组            for (int j = 0; j < i; j++) {                buf[j] = val[j];//先装起来前面没有需要替换的匹配过的数组            }            while (i < len) {                char c = val[i];                buf[i] = (c == oldChar) ? newChar : c;//后面的匹配替换                i++;            }            return new String(buf, true);//返回结果        }    }    return this;}

可见replace的替换char字符效率上是高replace替换字符串和replaceAll的,在效率上来说,如果处理字符串少,应该没什么问题的,但是如果处理超过几十万字符的计算那就非常耗时了,,或者替换的字符不多,可以用replace替换char的api,或者自己实现,因为遍历少,效率高。

测试效率可参考 别人写的文章https://blog.csdn.net/zhanglianyu00/article/details/78296277

2、然后我们字符串的拼接,我们可以使用加号 + 或者使用StringBuilder或StringBuffer的append,到底哪个好。

字符串的拼接 比如 String s = s1 + s2;这儿其实做了好几步,首先看s1是否在字符静态池中,java中有这个概念,有的话,就直接拿出来用,s2如果没有的话,就创建,然后第二步进行字符串的拼接,这儿按照个人理解是,它底层实现,或许是先开辟一个内存,然后对s1和s2进行复制到s指向地址的内存中,这样其实就是 1、静态字符池中查找、创建 2、开辟内存复制 ,过程自然比stringBuilder复杂多了。

StringBuilder 底部有个重要的代码

 

/** * Copies an array from the specified source array, beginning at the * specified position, to the specified position of the destination array.

//注释大概意思是 复制从指定源数组开始指定srcBegin开始复制指定需要复制的数组。翻译有点蹩脚~

System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);//主要是数组的复制,这个api底层是jni调用底层的实现

//依据个人最近学c的猜想,应该避免不了都是动态扩展内存,指针去扩充字符内容。遍历次数我觉得认为是1次可以解决。

然后我们看比较他们字符拼接效率:

public static void a() {

        long starTime = new Date().getTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 500000; i++) {

            sb.append(String.valueOf(i));

        }
        long endTime = new Date().getTime();
        System.out.println("“append”号底层替换花费时间:" + (endTime - starTime));
    }

    public static void b() {

        long starTime = new Date().getTime();
        String string = new String();
        for (int i = 0; i < 500000; i++) {
            string += i;
        }
        long endTime = new Date().getTime();
        System.out.println("“+=”号花费时间:" + (endTime - starTime));

    }

“append”号底层替换花费时间:47

“+=”号花费时间:3598

在我机器上运行是这样 StringBuilder拼接耗时47毫秒和 加号是3000多毫秒。所以我们尽量使用stringbuilder。

3、最后我们看下split,由于String.split方法会调用到CopyOfRange方法,在大数据量的情况下,效率很低,所以改用StringTokenizer类实现String.split的功能

StringTokenizer stringTokenizer = new StringTokenizer(dataStr,",");while(stringTokenizer.hasMoreTokens()){    String eme = stringTokenizer.nextToken();}

大概小结这样。

                                                                                                                      

转载于:https://my.oschina.net/u/3318187/blog/1944154

你可能感兴趣的文章
JS冒泡事件 与 事件捕获
查看>>
NetSetMan IP地址切换工具
查看>>
Lind.DDD敏捷领域驱动框架~Lind.DDD各层介绍
查看>>
单片机不同晶振怎么计算延迟时间?
查看>>
第 15 章 Div+CSS页面设计
查看>>
龙珠激斗大冒险掷筛子算法
查看>>
第 46 章 Regular expression (正则表达式)
查看>>
入坑IT都快十年了
查看>>
【spring Boot】spring boot获取资源文件的三种方式【两种情况下】
查看>>
(转) 机器学习很有趣Part6:怎样使用深度学习进行语音识别
查看>>
ASP.NET遇到HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容
查看>>
Android Gradle 自定义Task 详解
查看>>
数据结构之树、森林和二叉树的转换
查看>>
svn服务器配置以及自动同步到web服务器
查看>>
【VS2013】设定Nuget代理
查看>>
1211Bug with integer literals in PLSQL
查看>>
Linux 权限管理之目录权限限制
查看>>
再谈矩阵分解在推荐系统中的应用
查看>>
ABAP 面试问题及答案(一):数据库更新及更改 SAP Standard (转)
查看>>
Top 10 JavaScript编辑器,你在用哪个?
查看>>