Java—StringBuffer与StringBuilder的区别

来源:互联网 发布:网络水军怎么收费 编辑:程序博客网 时间:2024/05/28 15:33

Java定义了三种字符串操作类,分别是String,StringBuffer,StringBuilder.查看API文档得知这三个类的定义为:

  • public final class Stringextends Objectimplements Serializable, Comparable<String>, CharSequence
  • String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。

    字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。

  • public final class StringBufferextends Objectimplements Serializable, CharSequence
  • 线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

    可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

    StringBuffer 上的主要操作是 appendinsert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。 

  • public final class StringBuilderextends Objectimplements Serializable, CharSequence
  • 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。

    StringBuilder 上的主要操作是 appendinsert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。 

从定义来看三者都是最终(final)类且都实现了序列化(Serilizable)接口和有序字符集合(CharSequence)接口。String类则多实现了一个比较(Comparable)接口。那么这三者包含的方法有什么不同呢?笔者采用反射机制(reflection)对这三个类的方法进行了遍历与比较:

import java.lang.reflect.Method;public class ClassTest {public static void main(String[] args) throws ClassNotFoundException {System.out.println("String..................");printMethods("java.lang.String");System.out.println("StringBuffer..................");printMethods("java.lang.StringBuffer");System.out.println("StringBuilder..................");printMethods("java.lang.StringBuilder");}public static void printMethods(String classname)throws ClassNotFoundException {Class c = Class.forName(classname);Method[] fd = c.getDeclaredMethods();for (Method method : fd) {System.out.println(method.getName());}}}

String类的方法较其他两者多一倍,功能比较详尽,这也是作为Java早期API的优势,方法几乎没有遗漏,其余两者的方法则完全相同,但三者如果论实现的功能则没有太大差别。除了StringBuffer和StringBuilder上的appendinsert 方法在代码编写更方便快捷外,没有太多区别,在此不做细说。那么我们比较三者的方法实现的代码性能。

在日常操作中最常用的为字符串的拼接,我们以此来做实践。分别创建对象String,StringBuffer,StringBuilder 拼接字符串"This is a String"20000次。通过运行时间来判断性能。

public class StringOperateTimeCompare {final static String s = "This is a String.";public static void main(String[] args) {StringTest(20000);StringBufferTest(20000);StringBuilderTest(20000);}public static void StringTest(int x) {long begin = System.currentTimeMillis();String str = new String("String:");for (int i = 0; i < x; i++) {str += s;}long end = System.currentTimeMillis();System.out.println("This is StringTest,used :" + (end - begin));}public static void StringBufferTest(int x) {long begin = System.currentTimeMillis();StringBuffer str = new StringBuffer("String:");for (int i = 0; i < x; i++) {str.append(s);}long end = System.currentTimeMillis();System.out.println("This is StringBufferTest,used :" + (end - begin));}public static void StringBuilderTest(int x) {long begin = System.currentTimeMillis();StringBuilder str = new StringBuilder("String:");for (int i = 0; i < x; i++) {str.append(s);}long end = System.currentTimeMillis();System.out.println("This is StringBuilderTest,used :" + (end - begin));}}
运行结果:
This is StringTest,used :3814
This is StringBufferTest,used :2
This is StringBuilderTest,used :1

通过运行时间知单线程运行效率: String<<StringBuffer<StringBuilder。

在不考虑线程安全的情况下,推荐使用StringBuilder,运行效率最高。

如果需要考虑线程安全即同步问题则需要使用StringBuffer。

1 0