StringBuilder与StringBuffer作用就是用来处理字符串,但String类本身也具备很多方法可以用来处理字符串,那么为什么还要引入这两个类呢?

  首先看下面的例子

  public static void main(String[] args) {

  String str0 = "hel,lo,wor,l,d";

  long start = System.currentTimeMillis();

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

  str0 += i;

  }

  System.out.println(System.currentTimeMillis() - start);

  StringBuilder sb = new StringBuilder("hel,lo,wor,l,d");

  long start1 = System.currentTimeMillis();

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

  sb.append(i);

  }

  System.out.println(System.currentTimeMillis() - start1);

  StringBuffer sbf = new StringBuffer("hel,lo,wor,l,d");

  long start2 = System.currentTimeMillis();

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

  sbf.append(i);

  }

  System.out.println(System.currentTimeMillis() - start2);

  }

  上述代码中3处循环完成了同样的功能,字符串拼接,执行的结果如下:

  36823

  3

  4

  可以看出执行时间差别太大,为了解决String不擅长的大量字符串拼接这种业务场景,引入了StringBuffer和StringBuilder.

  首先我们分析一下为什么String在大量字符串拼接这种场景下这么慢?

  因为String本身不可变,我们对String的任何操作都会返回一个新的对象,然后当前String变量指向新的对象,而原来的String对象就会被GC回收,那么在循环中就会大量快速的创建新的对象,大量原来的对象会不断的被GC回收,消耗的时间是非常恐怖的,而且内存占用非常大。

  下面我们对比了String、StringBuffer与StringBuilder的区别

  String  StringBuffer  StringBuilder

  final修饰,不可继承  final修饰,不可继承  final修饰,不可继承

  字符串常量,创建后不可变  字符串变量,可动态修改  字符串变量,可动态修改

  不存在线程安全问题  线程安全,所有public方法由synchronized修改  线程不安全

  大量字符串拼接效率最低  大量字符串拼接效率非常高  大量字符串拼接效率最高

  StringBuffer与StringBuilder实现非常类似,下面以StringBuilder简单说明一下append()方法基本原理

  1. 首先创建一个StringBuilder

  StringBuilder sb1 = new StringBuilder();

  StringBuilder sb2 = new StringBuilder(100);

  StringBuilder对字符串的操作是通过char[]来实现的,通过默认构造器创建的StringBuilder,其内部创建的char[]的默认长度为16,当然可以调用重载的构造器传递初始长度(推荐这样,因为这样可以减少数组扩容次数,提高效率)。

  /**

  * Constructs a string builder with no characters in it and an

  * initial capacity of 16 characters.

  */

  public StringBuilder() {

  super(16);

  }

  2. StringBuilder的append()方法

  每次调用append(str)方法时,会首先判断数组长度是否足以添加传递来的字符串

  /**

  * Appends the specified string to this character sequence.

  *

  * The characters of the {@code String} argument are appended, in

  * order, increasing the length of this sequence by the length of the

  * argument. If {@code str} is {@code null}, then the four

  * characters {@code "null"} are appended.

  *

  * @param str a string.

  * @return a reference to this object.

  */

  public AbstractStringBuilder append(String str) {

  if (str == null)

  return appendNull();

  int len = str.length();

  ensureCapacityInternal(count + len);

  str.getChars(0, len, value, count);

  count += len;

  return this;

  }

  /**

  * For positive values of {@code minimumCapacity}, this method

  * behaves like {@code ensureCapacity}, however it is never

  * synchronized.

  * If {@code minimumCapacity} is non positive due to numeric

  * overflow, this method throws {@code OutOfMemoryError}.

  */

  private void ensureCapacityInternal(int minimumCapacity) {

  // overflow-conscious code

  if (minimumCapacity - value.length > 0) {

  value = Arrays.copyOf(value,

  newCapacity(minimumCapacity));

  }

  }无锡渤海医院做人流 http://www.89906662.com/

  如果传递的字符串长度 + 数组已存放的字符的长度 > 数组的长度,这时就需要进行数据扩容了

  /**

  * Returns a capacity at least as large as the given minimum capacity.

  * Returns the current capacity increased by the same amount + 2 if

  * that suffices.

  * Will not return a capacity greater than {@code MAX_ARRAY_SIZE}

  * unless the given minimum capacity is greater than that.

  *

  * @param minCapacity the desired minimum capacity

  * @throws OutOfMemoryError if minCapacity is less than zero or

  * greater than Integer.MAX_VALUE

  */

  private int newCapacity(int minCapacity) {

  // overflow-conscious code

  int newCapacity = (value.length << 1) + 2;

  if (newCapacity - minCapacity < 0) {

  newCapacity = minCapacity;

  }

  return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)

  ? hugeCapacity(minCapacity)

  : newCapacity;

  }

  扩容规则如下:默认将数组长度设置为“ (当前数组长度 * 2) + 2”,但如果按此规则扩容后的数组也不足以添加新的字符串,就需要将数组长度设置为“数组内字符长度 + 传递的字符串长度”。

  因此假如我们知道拼接的字符串大概长度有100多字符,我们就可以设置初始长度150或200,这样就可以避免或减少数组扩容的次数,从而提高效率。

Java基础 StringBuffer、StringBuilder原理浅析的更多相关文章

  1. Java基础-StringBuffer类与StringBuilder类简介

    Java基础-StringBuffer类与StringBuilder类简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.StringBuffer类 在学习过String类之后 ...

  2. Java基础(四) StringBuffer、StringBuilder原理浅析

    StringBuilder与StringBuffer作用就是用来处理字符串,但String类本身也具备很多方法可以用来处理字符串,那么为什么还要引入这两个类呢? 关于String的讲解请看Java基础 ...

  3. Java基础(五) final关键字浅析

    前面在讲解String时提到了final关键字,本文将对final关键字进行解析. static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提 ...

  4. Java String StringBuffer StringBuilder

    String  字符串常量存储在常量区,每次追加操作会创建新的对象: StringBuffer  字符串变量  线程安全 在堆上创建,每次追加操作在原对象上进行操作:  速度 StringBuffer ...

  5. Java中 StringBuffer StringBuilder String 区别

    String       字符串常量   不可变  使用字符串拼接时是不同的2个空间 StringBuffer  字符串变量   可变   线程安全  字符串拼接直接在字符串后追加 StringBui ...

  6. Java基础(33):StringBuilder的方法与应用实例(String相关类)

    Java 中的 StringBuilder 类的常用方法 重要的事情说三遍: 在需要频繁对字符串进行修改操作时使用 StringBuilder 的效率比 String 要高 在需要频繁对字符串进行修改 ...

  7. Java基础——StringBuffer和StringBuilder

    本节讲述2个字符串容器的区别 StringBuffer和StringBuilder区别: 1.相同点 两者都是容器(可变的字符序列),都可以对字符串进行基本的“增删改查”操作. 2.不同点 Strin ...

  8. java ——String , StringBuffer, StringBuilder类

    一.String类概述 1.String对象一旦创建就不能改变. 2.字符串常量池. 字符串常量池的特点:池中有则直接使用,池中没有则创建新的字符串常量. 例1: “==”  比较两个对象是否引用同一 ...

  9. java数据库连接池技术原理(浅析)

    在执行数据库SQL语句时,我们先要进行数据连接:而每次创建新的数据库的连接要消耗大量的资源,这样,大家就想出了数据库连接池技术.它的原理是,在运行过程中,同时打开着一定数量的数据库连接,形成数据连接池 ...

随机推荐

  1. (转)Loadrunner教程--常用操做流程

    1loadrunner压力测试一般使用流程 1.1loadrunner压力测试原理 本质就是在loadrunner上模拟多个用户同时按固定行为访问web站点.其中固定行为在loadrunner中是通过 ...

  2. yum提示problem making ssl connection的解决办法

    yum缓存提示problem making ssl connection的解决办法 缺少ssl证书认证本地获取的问题导致,解决办法如下: 执行命令:yum install -y ca-certific ...

  3. ES6 - 解构(数组和对象)

    解构对象 /** * 解构:快捷,方便 * * 对象解构 */ { var expense = { type: "es6", amount: "45" }; / ...

  4. django入门8之xadmin引入富文本和excel插件

    django入门8之xadmin引入富文本和excel插件 Xadmin引入富文本 插件的文档 https://xadmin.readthedocs.io/en/docs-chinese/make_p ...

  5. unity 如何打开本地文件夹,并选中文件

    public static void OpenDirectory(string path, bool isFile = false) { if (string.IsNullOrEmpty(path)) ...

  6. Linux下安装.NET Core

    环境 { "操作系统":"CentOS 7.5 64位", "CPU":"1核", "内存":&qu ...

  7. EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案安装使用常见问题的分析

    EasyNVR对于互联网的视频直播还是有着一定的贡献的.为了方便用户的体验使用,我们也在互联网上放置了对应的试用版本,并且也会随着功能是更新也会定期的更新上去.软件包也会配置对应的使用文档和说明. 许 ...

  8. jQuery prop方法替代attr方法

    jquery attr()方法获取标签的 checked 会有问题,所以用了 prop() 方法.

  9. 【Spring Cloud学习之四】Zuul网关

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 一.接口网关接口网关:拦截所有的请求,交由接口网关,然后接口网关进行转发,类似ngi ...

  10. vs2015下C4819该文件包含不能在当前代码页(936)中表示的字符问题解决

    今天编译IfcOpenshell出现很多warning如下: C4819 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode 格式以防止数据丢失 解决方案: 文件——& ...