字符串String是Java编程中使用概率最高的变量,也许你觉得没有什么可讲的,随手拈来,然而字符串的处理却尤其需要我们的关注,因为大量的字符串实例的随意创建,给系统的效率带来了很大的问题。

比如下面我们来做一个测试,对比String类和StringBuffer的执行效率:

●     String执行10000次累加

long start = System.currentTimeMillis();

String str = "";

for (int i = 0; i < 10000; i++) {

    str += "," + i;

}

long end = System.currentTimeMillis();

System.out.println(end - start);

执行的结果花费了702ms。

●     使用StringBuffer类来代替String类:

long start = System.currentTimeMillis();

StringBuffer str = new StringBuffer();

for (int i = 0; i < 10000; i++) {

    str.append(",").append(i);

}

long end = System.currentTimeMillis();

System.out.println(end - start);

运行共花费了0ms。

通过对比发现StringBuffer几乎不花费时间。这是因为,String对象的每一次累加,都会先将累加的字符串创建一个实例对象然后再累加,等于是创建了10000个实例。而StringBuffer每次都是修改的原有实例对象,只是创建了1个实例。通过学习第2章我们已经知道,创建实例需要申请内存地址、写入数据的过程,大量的这种操作就会消耗大量的CPU计算资源。

也许你会说,StringBuffer这么高效率,那我们不再使用String类就可以了,然而实际情况是,它们在不同的情况下各有选择的优势。通过《高手真经 Java核心编程技术》第11.2节的讲解可知,String、StringBuffer与StringBuilder三者最大的区别是:

●     String是字符串常量

●     StringBuffer是字符串变量(线程安全)

●     StringBuilder是字符串变量(非线程安全)

简要的说,String类型和StringBuffer类型的主要性能区别其实在于,String是不可变的对象,因此在每次对String类型进行改变的时候,其实都等同于生成了一个新的String对象,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM的GC就会开始工作,那速度是一定会相当慢的。

而如果是使用StringBuffer类则结果就不一样了,每次结果都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用StringBuffer,特别是字符串对象经常改变的情况下。而在某些特别情况下,String对象的字符串拼接其实是被JVM解释成了StringBuffer对象的拼接,所以这些时候String对象的速度并不会比StringBuffer对象慢,而特别是以下的字符串对象生成中,String效率是远要比StringBuffer快的:

String str = “This is only a” + “ simple” + “ test”;

StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:

String str = “This is only a” + “ simple” + “test”;

其实就是:

String str = “This is only a simple test”;

所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:

String str2 = “This is only a”;

String str3 = “ simple”;

String str4 = “ test”;

String str1 = str2 +str3 + str4;

这时候JVM会规规矩矩的按照原来的方式去做。

为了测试这三个类的累加不同次数字符串时的效率,我们编写一个测试类,分别按次数累加字符串:

程序11-8 TestString.java

package test.String;

public class TestString {

static int count = 100;//循环次数

// 测试String

public static void testString() {

long start = System.nanoTime();

String str = "";

for (int i = 0; i < count; i++) {

str += "," + i;

}

long end = System.nanoTime();

System.out.println("String:" + (end - start));

}

    // 测试StringBuffer

public static void testStringBuffer() {

long start = System.nanoTime();

StringBuffer str = new StringBuffer();

for (int i = 0; i < count; i++) {

str.append(",").append(i);

}

long end = System.nanoTime();

System.out.println("StringBuffer:" + (end - start));

}

    // 测试StringBuilder

public static void testStringBuilder() {

long start = System.nanoTime();

StringBuilder str = new StringBuilder();

for (int i = 0; i < count; i++) {

str.append(",").append(i);

}

long end = System.nanoTime();

System.out.println("StringBuilder:" + (end - start));

}

public static void main(String[] args) {

TestString.testString();

TestString.testStringBuffer();

TestString.testStringBuilder();

}

}

运行该程序执行的测试时间:

表11-2 测试结果

毫微秒

String

StringBuffer

StringBuilder

1次

69,562

46,934

8,101

10次

109,791

57,269

24,025

100次

431,619

172,089

128,228

1000次

8,274,236

876,368

270,985

1万次

704,425,841

2,673,524

1,388,166

10万次

溢出

20,926,961

11,669,361

100万次

溢出

246,871,041

137,586,760

String在10w次循环时就溢出了,而StringBuffer在100万次循环时间为246ms,StringBuilder的时间为137ms。显然选择优先级为:StringBuilder>StringBuffer>String。因此,对于这三个类的使用,我们需要按照以下情况去选择:

●     如果你偶尔对简单的字符串常量进行拼接,那么可以使用String,它足够简单而且轻量级;

●     如果你需要经常进行字符串的拼接、累加操作,请使用StringBuffer或StringBuilder;

●     如果是在单线程的环境中,建议使用StringBuilder,它要比StringBuffer快;如果是在多线程的环境中,建议使用StringBuffer,它是线程安全的;

因此,StringBuilder实际上是我们的首选,只有在多线程时才可以考虑使用StringBuffer,只有在字符串的拼接足够简单时才使用String。

本文出自《Java高手真经. 编程基础卷:Java核心编程技术:Java基础+核心库+图形+网络+高级特性》一书

转载于:https://www.cnblogs.com/haoxia/archive/2009/07/09/1519891.html

如何选择String相关推荐

  1. string类型比较_redis存json数据时选择string还是hash

    我们在缓存json数据到redis时经常会面临是选择string类型还是选择hash类型去存储.接下来我从占用空间和IO两方面来分析这两种类型的优势. 1.占用空间 根据数据结构的共识我们知道hash ...

  2. String.valueOf()方法与toString()方法的区别

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 两者都是把ObJect对象转化为String 类型. 2.string.valueof()方法 ...

  3. 一大波Java来袭(四)String类、StringBuilder类、StringBuffer类对照

    本文主要介绍String类.StringBuffer类.StringBuilder类的差别  : 一.概述 (一)String 字符串常量.可是它具有不可变性,就是一旦创建,对它进行的不论什么改动操作 ...

  4. Android如何愉快的使用Spinner列表选择框

    Android如何愉快的使用Spinner列表选择框 说实话 我刚学习的时候,感觉这就是网页上的select标签,不过,这个标签可以带图,哈哈 是不是感觉像 又到了我们粘贴代码的时间了 布局文件:ac ...

  5. Ionic2中的相册选择和拍照上传——ImgService

    目录 目录 前言 Cordova准备 ImgService服务的实现 ImgService服务的使用 示例效果 相册选择器的汉化 参考 前言 在APP中启动相册选择器或者拍照上传图片这些功能是非常常见 ...

  6. ListView 选择模式

    实际的应用APP开发中,基本上由自己来控制多选的逻辑,后来参考大神的作品,发现ListView本身已经实现了,下面就跟随我的足迹,一起探讨一下吧. ListView四种模式 /*** Normal l ...

  7. TVM apps extension示例扩展库

    TVM apps extension示例扩展库 此文件夹包含TVM的示例扩展库.演示了其它库如何在C++和Python API中扩展TVM. 该库扩展了TVM的功能. python模块加载新的共享库, ...

  8. 记住密码以及Android 列表的操作

    1.综合使用RecycleView,CardView,Adapter实现一个宝宝相册,并将其加入到实验一形成的应用中,使得:用户成功登录后转到宝宝相册所在的主界面.还要求实现:用户单击对应的列表子项的 ...

  9. 转载:Beginning WF 4.0翻译——第四章(传递参数)

    在第一章,我已经向你展示了在工作流中怎么使用variables(变量)和arguments(参数).跟编码类似,variables类似于类成员,而arguments类似于方法的参数.你已经在前三章使用 ...

最新文章

  1. java字符串转换成日期型对象
  2. 为什么 Python被Google选为TensorFlow的开发语言呢?使用 Python比C++语言进行机器学习有什么优势?
  3. linux重命名的命令行操作,Linux rename命令批量重命名的方法
  4. 我的同事Leo做的一个AR增强现实的项目
  5. Struts01---入门小案例
  6. Java中的硬件事务性内存,或者为什么同步将再次变得很棒
  7. android 模糊查询控件_第三十二篇:在SOUI2.0中像android一样使用资源
  8. 关于负载均衡的几个问题
  9. cad页面布局快捷键_炸裂“图纸集”功能、高手都在偷偷用的CAD图纸管理神器
  10. Python-装饰器进阶
  11. 登录界面实现记住密码功能
  12. 信息系统项目管理师(2022年) —— 第 1 章 信息化和信息系统
  13. Report Machine(RM)报表控件简单用法-delphi
  14. 漫谈工业软件(2)-IEC61499标准
  15. 推荐12个免费查找文献的学术网站,建议点赞、收藏!
  16. HL7解析类的使用(java)
  17. Shiro(一)之shiro简介与工作原理
  18. 浅谈SAP FICO—总账科目
  19. 录屏软件Camtasia9的录屏文件存储位置/好用的免费录屏软件代替
  20. ArcGIS图像配准技巧:配准获取中国气候区分布数据(附练习数据下载)

热门文章

  1. 通话录音_iOS14,通话录音终于来了!
  2. hibernate-jpa/hibernate-jpa-2.1-api-1.0.0.final.jar源代码下载地址
  3. 极客时间《玩转Git三剑客》之GItHub剑客
  4. C++ : 二进制法生成子集
  5. 面向对象回顾(构造函数、覆盖和重载、Query接口的list方法和iterate方法、面向对象的六原则一法则、反射、内部类)
  6. python 安装包时出现红字_Python从入门到就业-1.1节:安装Python
  7. 反问疑问_句子练习大全(反问、疑问、设问、病句等练习)
  8. linux socket API / bind
  9. nfs上安装oracle,使用NFS安装oracle软件
  10. python gpiozero,树莓派远程GPIO调试(Python + pigpio版)