关于java字符串常用一些api 效率比拼小结(java对大型的字符串api处理效率比拼)...

比如说我们要处理几十万个的字符串的处理,可能比如字符串的正则替换,比如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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值