文档章节

编写高质量代码:改善Java程序的151个建议(第4章:字符串___建议52~59)

素小暖OSC
 素小暖OSC
发布于 2019/07/17 13:43
字数 1655
阅读 216
收藏 2

生活不只眼前的苟且。还有读不懂的诗和到不了的远方。 --闫妮

建议52:推荐使用String直接赋值

建议53:注意方法中传递的参数要求

建议54:正确使用String、StringBuffer、StringBuilder

建议55:注意字符串的位置

建议56:自由选择字符串的拼接方法

建议57:推荐在复杂字符串操作中使用正则表达式

建议58:强烈建议使用UTF编码

建议59:对字符串持有一种宽容的心态

建议52:推荐使用String直接赋值

建议53:注意方法中传递的参数要求

建议54:正确使用String、StringBuffer、StringBuilder

1、Java String类

字符串广泛应用在Java编程中,在Java中字符串属于对象,Java提供了String类来创建和操作字符串。

需要注意的是String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且浪费有限的内存空间。

我们可以看到,初始String值为“hello”,然后在这个字符串后面加上新的字符串“world”,这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了“hello world”字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对经常性的字符串相关的操作,Java引入了两个新的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。

2、StringBuffer 和 StringBuilder 类

三者区别:

string:不可变字符序列

StringBuffer:可变字符序列、线程安全、效率低

StringBuilder:可变字符序列、线程不安全、效率高

注:

String的使用陷阱:

String  ss = "a";

ss +="b";

如果多次执行这些改变字符串内容的操作,会导致大量副本字符串对象存在内存中,降低效率。如果这样的操作放在循环中,会极大影响程序的性能。

3、性能测试

String的拼接与StringBuilder的使用对比,简单的12个字符串的循环解析拼接,相差了28毫秒,没有对比就没有伤害,以后用StringBuilder吧,暂时还不知道这个东西会有什么弊端,持续观察吧

ee4f3054569c9dee6d67fe1f0b1f096dda7.jpg

建议55:注意字符串的位置

public class Client55 {
    public static void main(String[] args) {
        String str1 = 1 + 2 + "apples";
        String str2 = "apples" + 1 + 2;
        System.out.println(str1);
        System.out.println(str2);
    }
}

答案是不一致,str1的值是"3apples" ,str2的值是“apples12”。

建议56:自由选择字符串的拼接方法

package OSChina.Client;

public class Client1 {
    public static void main(String[] args) {
        // 加号拼接
        String str = "";
        long start1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            str += "江疏影";
        }
        long end1 = System.currentTimeMillis();
        System.out.println("加号拼接耗时:" + (end1 - start1) + "ms");

        // concat拼接
        str = "";
        long start2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            str = str.concat("江疏影");
        }
        long end2 = System.currentTimeMillis();
        System.out.println("concat拼接耗时:" + (end2 - start2) + "ms");

        // StringBuilder拼接
        str = "";
        StringBuilder buffer = new StringBuilder("");
        long start3 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            buffer.append("江疏影");
        }
        long end3 = System.currentTimeMillis();
        System.out.println("StringBuilder拼接耗时:" + (end3 - start3) + "ms");

        // StringBuffer拼接
        str = "";
        StringBuffer sb = new StringBuffer("");
        long start4 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            sb.append("江疏影");
        }
        long end4 = System.currentTimeMillis();
        System.out.println("StringBuffer拼接耗时:" + (end4 - start4) + "ms");
    }
}

从上面的执行结果来看,在字符串拼接方式中,StringBuilder的append方法最快,StringBuffer的append方法次之(因为StringBuffer的append方法是线程安全的,同步方法自然慢一点),其次是concat方法,加号最慢,这是为何呢?

速度:StringBuilder>StringBuffer>concat>String+

原理:

1、“+”方法拼接字符串:

str= new StringBuilder(str).append("c").toString();

它与纯粹使用StringBuilder的append方法是不同的:一是每次循环都会创建一个StringBuilder对象,二是每次执行完毕都要调用toString方法将其转换为字符串——它的执行时间就耗费在这里了!

2、concat方法拼接字符串:我们从源码上看一下concat方法的实现,代码如下:

    public String concat(String str) {
        int otherLen = str.length();
        //如果追加字符长度为0,则返回字符串本身
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        //产生一个新的字符串
        return new String(buf, true);
    }

其整体看上去就是一个数组拷贝,虽然在内存中处理都是原子性操作,速度非常快,不过,注意看最后的return语句,每次concat操作都会创建一个String对象,这就是concat速度慢下来的真正原因,它创建了10万个String对象呀。

3、append方法拼接字符串:StringBuilder的append方法直接由父类AbstractStringBuilder实现,其代码如下:

public AbstractStringBuilder append(String str) {
   //如果是null值,则把null作为字符串处理
   if (str == null) str = "null";
   int len = str.length();
   ensureCapacityInternal(count + len);
   //字符串复制到目标数组
   str.getChars(0, len, value, count);
   count += len;
   return this;
}

整个append方法都在做字符数组处理,加长,然后拷贝数组,这些都是基本的数据处理,没有创建任何对象,所以速度也就最快。

4、StringBuffer的处理和此类似,只是方法是同步的而已。

建议57:推荐在复杂字符串操作中使用正则表达式

建议58:强烈建议使用UTF编码

注:一个系统使用统一的编码。

建议59:对字符串持有一种宽容的心态

中文的排序问题很混乱,Java使用UNICODE编码,而中文UNICODE字符集来源于GB2312,GB2312是一个包含了7000多个字符的字符集,它是按照拼音排序,并且是连续的,之后的GBK、GB18030都是在其基础上扩充而来的,所以要让它们完整的排序也就难上加难了。

如果排序对象是经常使用的汉字,使用Collator类排序完全可以满足我们的要求,毕竟GB2312已经包含了大部分的汉字,如果需要严格排序,则要使用一些开源项目来自己实现了。

注意:如果排序不是一个关键算法,使用Collator类即可。

 

编写高质量代码:改善Java程序的151个建议@目录

© 著作权归作者所有

素小暖OSC
粉丝 152
博文 96
码字总数 227968
作品 0
大连
私信 提问
素小暖讲编写高质量代码:改善Java程序的151个建议

本系列是用来记录《编写高质量代码 改善java程序的151个建议》这本书的读书笔记。方便自己查看,也方便大家查阅。 全书共12章,共有151条建议,其中1~3章针对java语法本身提出了51条建议;第4...

青衣霓裳
2019/07/09
724
3
《编写高质量代码 改善Java程序的151个建议》读书笔记

第7章 泛型和反射 建议94 不能初始化泛型参数的数组 Java的泛型在编译期有效,在运行期被删除,所有的泛型参数类型在编译后都会被擦出掉 Java泛型类和普通类在编译后都指向同一字节码 第8...

OSC_fly
2018/08/23
0
0
编写高质量代码:改善Java程序的151个建议(第1章:Java开发中通用的方法和准则___建议1~13)

作为一个由影视圈转行做Java的菜鸟来说,读书是很关键的,本系列是用来记录《编写高质量代码 改善java程序的151个建议》这本书的读书笔记。方便自己查看,也方便大家查阅。 建议1:不要在常量...

青衣霓裳
2019/07/09
372
2
编写高质量代码:改善Java程序的151个建议(第1章:Java开发中通用的方法和准则___建议14~20)

作为一个由影视圈转行做Java的菜鸟来说,读书是很关键的,本系列是用来记录《编写高质量代码 改善java程序的151个建议》这本书的读书笔记。方便自己查看,也方便大家查阅。 建议14:使用序列...

青衣霓裳
2019/07/11
157
0
《编写高质量代码:改善java程序的151个建议》笔记

前言: 很喜欢作者的前言: 对于java,我非常感激,从物质上来说,它给了我工作,帮我养家糊口;从精神上来说,它带给我无数的喜悦、困惑、痛苦、无奈------一如我们的生活。 第10章:性能和...

城固如春
2017/11/01
30
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 宇宙银河乱弹英雄传 —— @FalconChen

1Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @巴拉迪维 :Axxis的单曲《Only God Knows》 最近只听摇滚,挖了好多以前没听过的歌,蛮好。#今日歌曲推荐# 《Only God Knows》- Axxis 手机...

小小编辑
今天
280
2
Safari Date() 函数对日期时间字符串(yyyy-MM-dd HH:mm:ss) 提示NaN的问题

今天发现一个奇怪的问题,在iPhone使用 safari 选择定时发布文章到OSC,选择时间后提示不是合法的时间,判断时间的代码如下: var d = new Date('2020-01-23 23:15'); if (isNaN(d)) {...

FalconChen
昨天
140
0
ActiveMQ学习之通讯协议

一、支持的通讯协议 ActiveMQ支持的client-broker通讯协议有:TCP、NIO、UDP、SSL、HTTP(S)、VM 其中配置Transport Connector的文件在ActiveMQ安装目录的conf/activemq.xml中的<TransportCon...

冥焱
昨天
91
0
应急广播户户通平台

一、平台概述 应急广播户户通平台为软硬一体化广播服务解决方案。实现了应急广播、视音频及图片文字信息、调频及数字广播FM、天气预报信息接收功能,以及视音频播放、智能机器人、电子日历等...

neocean
昨天
133
0
如何为Apache 2.2启用mod_rewrite

我已经在我的Vista机器上安装了新的Apache 2.2,一切正常,除了mod重写。 我没有注释 LoadModule rewrite_module modules/mod_rewrite.s 但是我的重写规则都没有,即使是简单的重写规则 Re...

javail
昨天
53
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部