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. windows如何删除服务

    有时候软件被安装成了服务,但是卸载后如何删除无效的服务,这时候就不是普通用户就能删除了,这属于操作系统管理级别了,需要使用管理命令了. 管理员权限打开cmd,执行如下: C:\Windows\syst ...

  2. 异常值检验实战3_NBA球员表现稳定性分析

     机器学习_深度学习_入门经典(博主永久免费教学视频系列) https://study.163.com/course/courseMain.htm?courseId=1006390023&sh ...

  3. java agent 详细介绍 -javaagent参数

    java agent 详细介绍 简介 java agent是java命令的一个参数.参数 javaagent 可以用于指定一个 jar 包,并且对该 java 包有2个要求: 这个 jar 包的MAN ...

  4. sails0.12相关命令

    sails最新版本是1.2.3 如果要创建0.12的项目要使用以下命令 npm install sails@0.12 -g sails -vsails new myweb1npm audit fixc ...

  5. java面试题实战三

    华为优招面试经验. 1.笔试(这部分按照华为以前的风格不会为难人的,认真做AC一道题就可以进面试了,我编程能力一般吧,做了一道半而已,-_-||!) 2.测评(性格测试,不要太偏激就行了) 3.面试分 ...

  6. c++ Array运用实例

    myprint.hpp #include <iostream> #include <string> template <typename T> inline voi ...

  7. 【mybatis】子查询

    networkResource的 resultMap <resultMap id="NetworkResultMap" type="com.chinamobile. ...

  8. full text search

    definition https://www.techopedia.com/definition/17113/full-text-search A full-text search is a comp ...

  9. Sigmoid函数的替代:overflow encountered in exp in computing the logistic function

    RuntimeWarning: overflow encountered in exp in computing the logistic function 以下是sigmoid函数的标准写法,但是如 ...

  10. 【MongoDB学习之四】索引 聚合 备份与恢复 监控

    环境 MongoDB 4.0 CentOS 6.5_x64 一.索引语法ensureIndex()方法基本语法格式如下所示:>db.COLLECTION_NAME.ensureIndex({KE ...