StringBuilder 和 StringBuffer类
通常在涉及到StringBuilder和StringBuffer时中任何一个时,都应该想到另外一个并且在脑海中问自己是否用另外一个更加合适。
为什么这么说,请继续往下看,当然如果你已经对二者烂熟于胸自然就不必如此了。文章先介绍StringBuffer和StringBuilder,最后再
总结String(如果想要了解String的可以点击这里)、StringBuffer、StringBuilder之间的区别。
StringBuffer是什么
StringBuffer是一个线程安全的、可变的字符序列,它的父类是AbstractStringBuilder。到这里可能会有疑问,Buffer不是缓冲区的意思意思吗,应该叫做字符串缓冲区才对。
没错,两种叫法都没问题,因为Buffer之所以有缓冲作用,就是因为它预先开辟了一定大小内存空间,这个内存空间就是用来存放字符序列也就是具体需要的值。
底层数据结构:字符数组;
/**
* The value is used for character storage.
*/
char[] value;
常用方法:append()、insert()、reverse(),其中append是做追加;insert是做插入;reverse()函数是做字符串翻转。
刚入行Java的时候,经常会遇到一些笔试题,题目就是给一个字符串,然后需要写一个方法来完成这个功能。那时不知道有这个方法,愣是用字符数组加上循环写出来的。
此处只列举一部分,详细方法可以在JDK的源码中查看
append()
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;
value[index] = ch;
} @Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
} @Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
insert()
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
toStringCache = null;
super.insert(index, str, offset, len);
return this;
} /**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}
reverse()字符串翻转,这里可以看到真正翻转的逻辑是调用父类的reverse方法。
/**
* @since JDK1.0.2
*/
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}
reverse()父类实现。
/**
* Causes this character sequence to be replaced by the reverse of
* the sequence. If there are any surrogate pairs included in the
* sequence, these are treated as single characters for the
* reverse operation. Thus, the order of the high-low surrogates
* is never reversed.
*
* Let <i>n</i> be the character length of this character sequence
* (not the length in {@code char} values) just prior to
* execution of the {@code reverse} method. Then the
* character at index <i>k</i> in the new character sequence is
* equal to the character at index <i>n-k-1</i> in the old
* character sequence.
*
* <p>Note that the reverse operation may result in producing
* surrogate pairs that were unpaired low-surrogates and
* high-surrogates before the operation. For example, reversing
* "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
* a valid surrogate pair.
*
* @return a reference to this object.
*/
public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}
StringBuilder是什么
StringBuilder是一个可变的字符序列。
底层数据结构,常用方法:同StringBuffer
String,StringBuffer,StringBuilder 比较
通过了解String的源码可以知道,String对象的值是被final修饰符修饰的,所以一旦确定值,再去做变更就必须要重新指定引用地址,新引用地址意味着要开辟新的栈内存,
那么这里就会出现旧的引用被浪费,需要等待回收机制对其进行回收。
如果现在有一个字符串需要频繁改变,此时就必须要用StringBuilder或者StringBuffer。因为StringBuffer和StringBuilder都是字符数组,我们知道
数组的长度是可变的。一旦字符串发生变化,不需要和String那样重新开辟栈内存,而是在原来的基础上对数组进行内容进行变更,如果内容超过默认长度的话则会自动扩充,以满足变更之后的需求。
细心的朋友可能已经发现在介绍StringBuilder的时候,对于底层数据结构和常用的方法使用的是和StringBuffer相同,唯独第一句话明确的写出来了。因为StringBuffer和StringBuilder的最主要的区别就在于,StringBuffer是线程安全的而StringBuilder不是线程安全的。
归结起来就是String的值是final的,变更需要重新创建栈内存,因此不但会造成旧的栈内存空间的浪费,而且由此导致更多的垃圾需要被回收机制回收,耗费性能。
StringBuffer和StringBuilder则没有此弊端。而StringBuffer相比StringBuider适合多线程因为它是线程安全的所有操作值得方法都用synchronized修饰;StringBuilder则适合单线程的场景,没有同步方法效率较高相比StringBuffer来说。
结语
以上就是三者的异同分析,StringBuffer是在JDK1.0就有的,而StringBuilder在JDK1.5才加入,依据比对结果来看应该是为了让程序在单线程有更好的表现才曾加的StringBuilder。下面是StringBuilder源码中的一句介绍。
A mutable sequence of characters. This class provides an API compatible
with {@code StringBuffer}, but with no guarantee of synchronization.
如果对StringBuffer和StringBuilder的默认长度是多少,在数据超过默认长度之后,底层数组又是如何扩充感兴趣的可以自己去研究一下源码。
世上无难事只怕有心人。共勉之。
StringBuilder 和 StringBuffer类的更多相关文章
- 解析Java中的String、StringBuilder、StringBuffer类(一)
引言 String 类及其相关的StringBuilder.StringBuffer 类在 Java 中的使用相当的多,在各个公司的面试中也是必不可少的.因此,在本周,我打算花费一些时间来认真的研读一 ...
- [19/03/15-星期五] 常用类_String类&StringBuilder和StringBuffer类
一.基本概念 String 类对象代表不可变的Unicode字符序列,因此我们可以将String对象称为“不可变对象”. 那什么叫做“不可变对象”呢? 指的是对象内部的成员变量的值无法再改变.Str ...
- java 常用类库:String ; StringBuilder和StringBuffer类
1. String 1.String对象是不可变的 String类的value属性是用来存放字符串里面的值的.这个属性是被final修饰的.final修饰的变量不能够被第二次赋值,所以字符串是不可变的 ...
- String、StringBuilder和StringBuffer类
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- java String,StringBuilder和StringBuffer类的区别
对String而言: String是只读字符串,所引用的字符串不能被改变,一经定义,无法再增删改. String 定义的字符串保存在常量池里面,进行+操作时不能直接在原有基础上拼接. 每次+操作 : ...
- java中String类、StringBuilder类和StringBuffer类详解
本位转载自http://www.cnblogs.com/dolphin0520/p/3778589.html 版权声明如下: 作者:海子 出处:http://www.cnblogs.com/dolp ...
- 一大波Java来袭(四)String类、StringBuilder类、StringBuffer类对照
本文主要介绍String类.StringBuffer类.StringBuilder类的差别 : 一.概述 (一)String 字符串常量.可是它具有不可变性,就是一旦创建,对它进行的不论什么改动操作 ...
- 探秘Java中的String、StringBuilder以及StringBuffer
探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...
- 探秘Java中String、StringBuilder以及StringBuffer
探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...
随机推荐
- Java学习之classpath
要运行class文件,必须在class文件所在的目录下,那么是不是也可以通过设置系统变量来配置呢,当然有了classpath就来了 环境变量配置有两种 1.一劳永逸的 2.set 临时变量 我们用临时 ...
- adis16405 配置
- 力扣算法题—150. Evaluate Reverse Polish Notation
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, ...
- centos7升级php5.4到php5.6
history命令历史 8 yum provides php #自带的只有5.4版本 9 rpm -Uvh https://mirror.webtatic.com/yum/el7/epel-relea ...
- (PASS)java中打印当月的日历的每一天
package test; import java.time.DayOfWeek; import java.time.LocalDate; /** * * @ClassName: Calendar ...
- 固定Linux虚拟IP地址
由于我的开发环境是在VMWare虚拟机里安装Centos,然后在host文件中设置拦截,这样就可以直接跳转虚拟机的CentOS,但是虚拟机的IP地址总是会变,就要随时修改host文件,很麻烦.决定虚拟 ...
- bootstrap 基础模板相关信息
<!DOCTYPE html> <html> <head> <title></title> <link rel="style ...
- 通过网络socket获取对方 ip 和port
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);描述获取socket的对方地址struct sockaddr_in ...
- Java高新技术第二篇:反射技术
今天我们来看一下Java中的反射技术: 首先来了解一下Java中的反射的一些概念: Java中的反射是1.2引入的 反射的基石:class类 Class类的各个实例对象分别对应各个类在内存中的字节码, ...
- 反演+分块套分块——bzoj2154
题解都在论文里了 #include<bits/stdc++.h> using namespace std; #define maxn 10000005 #define ll long lo ...