[Java]StringBuffer/StringBuiler的区别与基本用法

这篇文章主要记录下个人学习过程中掌握的StringBuffer类与StringBuilder类的区别和用法。

我们先从源码上分析下StringBuffer与StringBulier的异同及实现原理。

源码部分

两者间的区别

StringBuilder类:

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence

StringBuffer类:

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuffer>, CharSequence

不难发现两个类在继承和实现接口方面有高度的一致性,譬如都继承了AbstractStringBuilder类,都实现了Serializable、Cmperable接口等。实际上,两个类的功能基本是完全等价的。

进一步观察以下源码:
StringBuffer类:

	@Override
    public synchronized int compareTo(StringBuffer another) {
        return super.compareTo(another);
    }

StringBuilder类:

	@Override
    public int compareTo(StringBuilder another) {
        return super.compareTo(another);
    }

上述代码以其中一个方法为例,我们可以发现StringBuffer类相较于StringBuilder类,其中的方法被声明为了synchronized,即“线程安全的”。 实际上,StringBuffer类的大多数方法都是被声明为synchornized。

由此,我们可以总结出二者之间的一些异同和应用方面的选择:

  1. StringBuffer类与StringBuilder类大体上的功能基本一致,他们继承于同一个抽象父类。
  2. StringBuffer类中大多数方法都采用了synchornized关键字进行修饰,因此它可以被认为是线程安全的。而相较于StringBuffer类,我们可以认为StringBuilder类是线程不安全的。
  3. StringBuilder类主要用于单线程操作,它线程不安全,但是效率更高;StringBuffer则适合多个线程同时进行操作,效率不高但可以保证操作的正确性。

从上述我们已经知道,二者在方法功能上并没有太大区别,为避免赘述,下文仅用StringBuilder类来探讨二者的方法应用。

扩容机制

StringBuilder类的扩容机制不算复杂,但要讲详细的同时讲清楚还是比较占据篇幅的。这里只说一下结论,StringBuilder底层也是通过数组进行存储,若数组容量不足,则会对数组进行扩容。默认情况下会扩容为原来容量的2倍+2,同时复制原有数组的元素到新的数组中。

这一部分若想深入了解可以参考下其他博主的文章,或者稍后我会单独写一篇专门分析这个机制的文章再链接到此。

应用部分

构造器

StringBuilder类常用的构造器有三个。

		StringBuilder sb1 = new StringBuilder();			// 空参,初始数组默认容量16
		StringBuilder sb2 = new StringBuilder(128);			// 以128作为初始数组的容量
		StringBuilder sb3 = new StringBuilder("hello");		// 将传入的字符串存储在数组中,若容量不够会进行扩容

常用方法

StringBuilder类的常用方法其实与String类相差不大,主要的一点区别即是对于需要修改字符串内容的方法,StringBuilder类不再像String类那样需要将一个新的String类作为返回值返回,而是直接在当前对象中进行修改。(注意并不是说StringBuilder类的方法就没有返回值了)

方便归类,我简要地将StringBuilder类的常用方法分为以下几个部分:增、删、查、改和其他

append(CharSequence s),在已储存的字符序列末尾添加新的字符序列,有众多的重载类型:

		sb1.append("hello");							// 直接传入一个String
		sb1.append("hello",1,3);						// 截取传入String的部分再进行添加,区间左闭右开
		sb1.append(new char[]{'a','b','c','d'});		// 直接传入一个char数组
		sb1.append(new char[]{'a','b','c','d'},1,2);	// 截取部分char数组,同样左闭右开
		// ...还有一些不常用的重载方法在此不做赘述

返回值为当前对象本身的引用:

		StringBuffer s1 = new StringBuffer("abc");
        StringBuffer s3 = s1.append(1);
        s1.append(2);
        System.out.println(s3); // abc12
        System.out.println(s1); // abc12

delete(int start, int end),删除区间内的字符序列,左闭右开。

		s1.delete(2,4);
		System.out.println(s1); // ab2

charAt(int n):获取索引位置的字符。

		s1.charAt(0); // a

这一方面主要有两个方法。

setCharAt(int n, char ch):修改索引位置的元素。

		s1.setCharAt(2, c); // abc

replace(int start, int end, String str):修改左闭右开区间内的字符序列为传入的字符串。

		s1.replace(0,2,"12"); // 12c

其他

insert(int offset, String str):在指定索引位置插入新的字符序列,含重载方法,这里仅介绍最常用的一种。

		s1.insert(2, "here"); // 12herec

length():获取字符序列长度。

字符序列遍历方法:for循环+charAt():

		for( int i = 0 ; i < s1.length() ; i++ )
			System.out.print(s1.charAt(i));

关于StringBuilder与StringBuffer类的基本方法与String类其实比较类似也比较简单,就先介绍到这里。

猜你喜欢

转载自www.cnblogs.com/wyxBlogs/p/13174019.html