首页 > 其他分享 >String、StringBuffer、StringBuilder 的区别?

String、StringBuffer、StringBuilder 的区别?

时间:2023-07-09 20:47:29浏览次数:37  
标签:String StringBuffer System 线程 StringBuilder 字符串

一. 介绍 String、StringBuffer、StringBuilder:  

   前言: String、StringBuffer、StringBuilder 均在java.lang包下;

    String: 在Java中,String是一个特殊的引用类型,用于表示文本字符串。它提供了许多方法来操作和处理字符串,比如连接、截取、查找、替换等。String类内部使用字符数组(char[])来存储字符串的内容,且value字段被final修饰,这意味着String对象一旦创建后,其值就不可改变。String对象的值存储在常量池中,每次修改操作都会创建一个新的字符串对象,并且如果常量池中已经存在相同内容的字符串,就会直接引用该字符串而不创建新对象。

    StringBuffer:Java中的一个可变字符串类,用于处理字符串。它可以被修改,因此适合在需要频繁更改字符串内容的情况下使用。StringBuffer提供了许多方法用于插入、删除和修改字符串,并且支持线程安全操作。与String类不同,StringBuffer对象可以在已有的字符串基础上进行操作,且地址值不会改变;StringBuffer 类是可变的,它不会在常量池中创建新的常量。当你使用 StringBuffer 修改一个字符串时,它会在堆内存中创建一个新的字符串对象,并且在需要的时候调整其容量。

    StringBuilder:与StringBuffer类似,它允许在已有字符串的基础上进行修改、添加和删除操作,而不需要创建新的字符串对象。通过使用StringBuilder,可以高效地进行字符串拼接、插入、替换等操作,特别适用于频繁修改字符串内容的场景,每次修改只是对自身做出修改。StringBuilder具有较高的性能和效率,并且是线程不安全的,适用于单线程环境下的字符串处理。

 

二. 区别:

  1. 不可变性:

  • String类是不可变的,一旦创建就不能被修改。任何对字符串的操作都会创建一个新的字符串对象。
  • StringBuffer和StringBuilder类是可变的,可以在原始字符串上进行修改,无需创建新的对象。

  2. 线程安全性:

  • String类是线程安全的,因为它的方法在内部使用了同步机制,适用于多线程环境。
  • StringBuffer类是线程安全的,所有的方法都使用了同步锁,可以在多线程环境中使用。
  • StringBuilder类是非线程安全的,它的方法没有使用同步锁,适用于单线程环境。

  3. 性能:

  • 由于String类的不可变性,每次进行拼接、替换等操作时都会创建新的对象,对性能有一定影响。
  • StringBuffer类是可变的,适用于频繁操作字符串的情况,但是由于使用了线程安全同步机制,相对较慢。
  • StringBuilder类是可变的,适用于单线程下频繁操作字符串的情况,在性能上优于StringBuffer。

  综上所述,如果你需要进行频繁的字符串拼接、替换等操作,并且在多线程环境下使用,应该选择StringBuffer类。如果在单线程环境下进行字符串操作,可以选择StringBuilder类以获得更好的性能。而如果你不需要修改字符串,只是进行简单的字符串操作,那么使用String类即可。

 

三. 代码展示

 不可变性区别展示:

public static void main(String[] args) {
       // String 
        String str = "Hello";
        System.out.println(System.identityHashCode(str));
        String str1 = str + "word";
        System.out.println(System.identityHashCode(str1));

       // StringBuilder
        StringBuilder sb = new StringBuilder("Hello");
        System.out.println(System.identityHashCode(sb));
        StringBuilder sb1 = sb.append("word");
        System.out.println(System.identityHashCode(sb1));

       // StringBuffer
        StringBuffer sbf = new StringBuffer("Hello");
        System.out.println(System.identityHashCode(sbf));
        StringBuffer sbf1 = sbf.append("word");
        System.out.println(System.identityHashCode(sbf1));

    }

输出结果:
    23934342
    22307196
    10568834
    10568834
    21029277
    21029277

// 此方法中可以看到String是不可变,每次修改操作都会创建一个新的字符串对象,而StringBuffer、StringBuilder每次修改都不会改变自身的地址。

  JAVA是在jvm虚拟机上运行的,只能查看jvm中地址的哈希码,要想得到String类型在物理内存中的真实地存,那只有用JNI技术调用c/c++去实现,因此使用identityHashCode() ,该方法会返回对象的hashCode,不管对象是否重写了hashCode方法。

 

四. 总结

  • String:不可变的字符串,线程安全,适合在多线程环境下使用,适用于字符串内容不经常改变的情况,操作少量的数据。
  • StringBuffer:可变的字符串,线程安全,适合在多线程环境下使用,适用于频繁进行字符串操作的情况。
  • StringBuilder:可变的字符串,非线程安全,适合在单线程环境下使用,适用于频繁进行字符串操作的情况。

 

五. 扩展

  1. String 源码中注释

 * Strings are constant; their values cannot be changed after they
 * are created. String buffers support mutable strings.
 * Because String objects are immutable they can be shared. 

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

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
}

   private final char value[];  底层是字符数组实现,该值是使用final修饰,创建后不能改变。 

 

  2. StringBuffer 源码中注释

 * A thread-safe, mutable sequence of characters.
 * A string buffer is like a {@link String}, but can be modified.

 * The principal operations on a {@code StringBuffer} are the
 * {@code append} and {@code insert} methods, which are
 * overloaded so as to accept data of any type.

 * Whenever an operation occurs involving a source sequence (such as
 * appending or inserting from a source sequence), this class synchronizes
 * only on the string buffer performing the operation, not on the source.

  * 线程安全的可变字符序列,字符串缓冲区类似于String,但是可以修改。

  * 主要操作是通过append()、insert() 它们是重载的,以便接受任何类型的数据。

  * 每当涉及到源数据的操作发生改变时,(例如从源序列追加或插入)此类进行同步仅在执行操作的字符串缓冲区上,而不是在源数据上。

    @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;
    }

   StringBuffer 在插入或修改的时候 都会使用synchronized() 确保线程安全性。

 

  3. StringBuilder 源码注释

 * A mutable sequence of characters.  This class provides an API compatible
 * with {@code StringBuffer}, but with no guarantee of synchronization.
 * This class is designed for use as a drop-in replacement for
 * {@code StringBuffer} in places where the string buffer was being
 * used by a single thread (as is generally the case).   Where possible,
 * it is recommended that this class be used in preference to
 * {@code StringBuffer} as it will be faster under most implementations.

 * Instances of {@code StringBuilder} are not safe for
 * use by multiple threads. If such synchronization is required then it is
 * recommended that {@link java.lang.StringBuffer} be used.

  * 可变的字符串,此类提供与StringBuffer兼容的API,但不保证同步。这个类通常情况下用在字符串缓冲区被单个线程使用的地方,作为StringBuffer的替代品。建议优先使用此类而不是StringBuffer,因为在大多数实现中它会更快。

   * StringBuilder的实例对于多个线程使用是不安全的。如果需要同步,则建议使用StringBuffer

    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

  如果需要线程安全同步,建议使用StringBuffer类。

 

(๑′ᴗ‵๑) 完! 

 

标签:String,StringBuffer,System,线程,StringBuilder,字符串
From: https://www.cnblogs.com/victor-sin/p/17539163.html

相关文章

  • String内存模型和Java常用方法
    一、String内存模型1、直接赋值创建string对象内存原理:StringTable(串池):字符串常量池,用来存储字符串,只能是在直接赋值中使用才会存在串池当中(JDK7前串池是在方法区里面,StringTable(串池)在JDK7版本开始从方法区中挪到了堆内存,但是运行机制没有发生变化)eg:首先mian方法进栈,创建变......
  • Object.equals 和 String.equals的区别
    一. 源码展示:1.Object.equals:①引用类型地址值比较,直接返回结果:true||falsepublicclassObject{publicbooleanequals(Objectobj){return(this==obj);}} 2.String.equals:①判断地址值是否相等,若相等返回true,若不......
  • AtCoder Grand Contest 058 D Yet Another ABC String
    洛谷传送门AtCoder传送门OrzH6_6Q,感谢他给我们带来了这道容斥好题。这个东西看起来很不好搞。可以尝试容斥。但是我们要容斥啥?钦定ABC不出现,其他任意?感觉还是很难算。观察不合法子串,发现它们很有特点。如果我们钦定\(\texttt{A}\)为\(0\),\(\texttt{B}\)为\(1\),\(\te......
  • [oeasy]python0071_字符串类型_str_string_下标运算符_中括号
    回忆上次内容上次分辨了静态类型语言动态类型语言 python属于对类型要求没有那么严格的动态类型语言 对初学者很友好不过很多时候也容易弄不清变量类型 直接修改代码增强程序的可读性把变量的类型明确标......
  • C++黑马程序员——P193-196. string容器 字符串比较,字符存取,字符串插入和删除,子串
    P193.string容器——字符串比较P194....——字符存取P195....——字符串插入和删除P196....——子串获取P193.字符串比较 ——————————————————————————————————————————————————————————1//字符......
  • C++黑马程序员——P189-192. string容器 构造函数,赋值,拼接,查找和替换
    P189.string容器——构造函数P190....——赋值操作P191....——字符串拼接P192....——字符串查找和替换P189.构造函数———————————————————————————————————————————————————————————————......
  • API和String字符串介绍
    API1、如何使用Java已经写好的东西(方法,类)API(Applicationprogramminginterface):应用程序编程接口简单理解:API就是别人已经写好了的东西,我们不需要自己编写,直接使用即可啊Publicstaticvoidmain(String[]args){ Randomr=newRandom(); intnumber=r.nextInt(100);}......
  • Python如何实现docstring
    docPython语言从排版上看强制要求了一些书写规范,算是强制赋予了每个程序员一个"代码洁癖"。作为规范的一部分,可以在在类函数的开始增加注释,并且语言本身为这种注释做了"背书":可以通过help展示这个帮助文档的内容。这个本来是Python一个很细小的功能,也是一个很有意思的语法糖(因......
  • 【补题记录】 Codeforces Round 797 (Div. 3) F Shifting String(置换环)
    CodeforcesRound797(Div.3)FShiftingString思路:根据这个排列进行替换的操作可以往置换环考虑,就是对于每一段字串,它的变换都是有规律的,经过一定的操作之后都会回到原点,可以想象转化成图上问题。参考ygg的题解,直接用链表模拟这个转化的过程,然后暴力计数,因为要满足所有点都......
  • SPOJ Substrings 题解
    \(\text{SAM}\)入门好题。首先我们需要知道几个关于\(\text{SAM}\)的结论。结论1:题目中的\(f(x)\)单调下降。显然,对于长度为\(x\)的子串,其必存在一个\(x-1\)的后缀,这个后缀的\(\text{endpos}\)集合肯定包含子串的\(\text{endpos}\)集合,所以必有\(f(x-1)\le......