StringBuffer 和 StringBuilder 总结

StringBuffer 和 StringBuilder
介绍
大多数情况下, StringBuffer 的速度要比 String 快; StringBuilder 要比StringBuffer快;StringBuffer 和 StringBuilder 都是 AbstractStringBuilder 的子类,区别在于StringBuffer 的方法大部分都有 synchronized 修饰。
源码解析
AbstractStringBuilder
变量及构造方法
/**
* 用来存储字符的数组
* The value is used for character storage.
*/
char[] value;
/**
* 字符个数
* The count is the number of characters used.
*/
int count;
/**
* This no-arg constructor is necessary for serialization of subclasses.
*/
AbstractStringBuilder() {
}
/**
* 在构造方法中指定字符数组的长度
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
扩容
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
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;
}
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
扩容的方法最终由 newCapacity() 实现的,首先将容量左移一位(即扩大2倍)同时加2,如果此时任小于指定的容量,那么就将容量设置为 minimumCapacity 。然后判断是否溢出,通过 hugeCapacity 实现,如果溢出了(长度大于 Integer.MAX_VALUE ),则抛错( OutOfMemoryError );否则根据 minCapacity 和 Integer.MAX_VALUE - 8 的大小比较确定数组容量为 max(minCapacity, Integer.MAX_VALUE - 8)。最后将 value 值进行拷贝,这一步显然是最耗时的操作。
append() 方法
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;
}
append() 是最常用的方法,它有很多形式的重载。上面是最常用的一种,用于追加字符串。如果 str 是 null ,则直接调用
appendNull() 方法。这个方法就是直接追加 'n' 、 'u' 、'l'、'l' 这几个字符,方法如下:
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
如果不是null,则首先需要判断数组容量是否足够,不够则需要扩容(扩容则是调用上述分析的扩容方法);
然后调用 String 的 getChars() 方法将 str 追加到 value 末尾;
最后返回对象本身,所以 append() 可以连续调用(就是一种类似于链式编程)。
思考
- 为什么每次扩容是扩容为原来的两倍?
个人觉得是为了避免经常扩容带来的成本消耗。 - 为什么会加2呢?
个人也没想出什么好的解释,觉得可能是因为Java开发者认为我们在append数据的时候,中间经常会加一个分隔符,恰好这个分隔符在Java中正好占用两个字节。也不知道分析的对不对,有其他意见的大佬们可以在 issue
中进行讨论。
StringBuilder 与 StringBuffer 方法对比
通过查看源码分析发现两者都继承至 AbstractStringBuilder 。 而 StringBuffer 之所以是线程安全的,是因为重写 AbstractStringBuilder 的方法的时候在前面加上了 synchronzied 修饰这些方法;而 StringBuilder 重写的时候只是直接调用父类的方法,没有做其他的操作。
其实通过阅读源码发现 StringBuilder 和 StringBuffer 之间的关系,类似于 HashMap 和 HashTable 之间的关系。
StringBuffer 和 StringBuilder 总结的更多相关文章
- 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率
之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...
- String、StringBuffer与StringBuilder之间区别
关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下 1.三者在执行速度方面的比较:StringBuilder > String ...
- 关于StringBuffer和StringBuilder
StringBuffer 字符串特点:字符串是常量:它们的值在创建之后不能更改. 字符串的内容一旦发生了变化,那么马上会创建一个新 的对象. 注意: 字符串的内容不适宜频繁修改,因为一旦修改马上就会创 ...
- 谈谈StringBuffer和StringBuilder
(1) 速度 在执行速度方面的比较:StringBuilder > StringBuffer > String ①String 是不可变的对象(String类源码中存放字符的数组被声明为f ...
- (转)String、StringBuffer与StringBuilder之间区别
原文地址: http://www.cnblogs.com/A_ming/archive/2010/04/13/1711395.html 关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺 ...
- Java中String、StringBuffer、StringBuilder区别与理解
一.先比较String.StringBuffer.StringBuilder变量的HashCode值 使用System.out.println(obj.hashcode())输出的时对象的哈希码, 而 ...
- String、Stringbuffer、StringBuilder的区别(转载)
最近学习到StringBuffer,心中有好些疑问,搜索了一些关于String,StringBuffer,StringBuilder的东西,现在整理一下. 关于这三个类在字符串处理中的位置不言而喻,那 ...
- String、StringBuffer和StringBuilder的深入解析
今天闲来无事,整理了下平时记录在印象笔记里的java开发知识点,整理到String,StringBuffer以及StringBuilder的区别时突然又产生了新的疑惑,这些区别是怎么产生的?温故为何能 ...
- String、StringBuffer、StringBuilder的区别
在日常开发过程中String字符串估计是被用到最多的变量了,最近看了一些String.StringBuffer和StringBuilder的东西,三者都可以对字符串进行操作,他们究竟有什么区别,以及适 ...
- Java String,StringBuffer和StringBuilder的区别
[可变与不可变] String是字符串常量,不可变. StringBuffer和StringBuilder是字符串变量,可变. [执行速度方面] StringBuilder > StringBu ...
随机推荐
- 自动配置/切换/查看JDK环境变量
最近老是需要几个版本的JDK切换工作,于是网上收集资料整理,自己写了一个:自动配置/切换/查看JDK环境变量的批处理脚本.顺带3个JDK版本分别是:jdk1.6.0_43,jdk1.7.0_80,jd ...
- maven整合eclise
-Dmaven.multiModuleProjectDirectory=$M2_HOME
- 如何在MySQL中使用explain查询SQL的执行计划?
1.什么是MySQL执行计划 要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有简单的了解. MySQL本身的功能架构分为三个部分,分别是 应用层.逻辑层.物理层,不只是MyS ...
- BZOJ 1733: [Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 网络流 + 二分答案
Description Farmer John is constructing a new milking machine and wishes to keep it secret as long a ...
- android读取xml
/*** 从config.xml中获取版本信息以及应用id* * @param urlPath* @return* @throws Exception*/public List getUpdateIn ...
- (8)Linux(客户端)和Windows(服务端)下socket通信实例
Linux(客户端)和Windows(服务端)下socket通信实例: (1)首先是Windows做客户端,Linux做服务端的程序 Windows Client端 #include <st ...
- Twice Equation
题目链接:https://nanti.jisuanke.com/t/A1541 题意:给你一个L,要你求一个不小于L的最小数字n,对于一个整数m,满足2*(m+1)*m=n*(n+1). 思路:打表找 ...
- three arrays
three arrays 字典树上贪心 #include<bits/stdc++.h> using namespace std; ][][]; ][]; ]; ]; ][]; ][]; i ...
- Solr集群环境搭建
一.准备工作 首先保证已经安装JDK工具包: [root@localhost opt]# java -version java version "1.8.0_144" Java(T ...
- #20175201张驰 实验三 敏捷开发与XP实践
实验步骤 (一)敏捷开发与XP 一.敏捷开发与XP实践-1 ①实验要求: 敏捷开发与XP实践 http://www.cnblogs.com/rocedu/p/4795776.html, Eclipse ...