String vs StringBuffer vs StringBuilder

字符串是Java中最广泛使用的类之一。StringBuffer和StringBuilder类提供了操作字符串的方法。我们将深入探讨StringBuffer和StringBuilder之间的区别。StringBuffer vs StringBuilder是一个热门的Java面试问题。

String vs StringBuffer vs StringBuilder

字符串是核心Java面试中最重要的主题之一。如果你正在编写一个在控制台上打印内容的程序,你会使用String。本教程旨在重点介绍String类的主要特性。然后我们将比较StringBuffer和StringBuilder类。

Java中的字符串

  1. String类表示字符字符串,我们可以用两种方式实例化String。

    String str = "ABC";
    // 或者 
    String str = new String("ABC");
    
  2. 在Java中,String是不可变的。因此,在多线程环境中使用是合适的。我们可以在函数之间共享它,因为不会有数据不一致的问题。

  3. 当我们使用双引号创建字符串时,JVM首先在字符串池中查找具有相同值的字符串。如果找到,则返回池中字符串对象的引用。否则,在字符串池中创建字符串对象并返回引用。JVM通过在不同线程中使用相同的字符串来节省大量内存。

  4. 如果使用new运算符创建字符串,它将在堆内存中创建。

  5. +运算符对字符串进行了重载。我们可以使用它来连接两个字符串。尽管在内部它使用StringBuffer来执行此操作。

  6. String重写了equals()hashCode()方法。只有当两个字符串具有相同的字符序列时,它们才相等。equals()方法区分大小写。如果要进行不区分大小写的检查,应使用equalsIgnoreCase()方法。

  7. 该字符串使用UTF-16编码进行字符流处理。

  8. String是一个final类。除了“private int hash”之外,所有字段都是final的。该字段包含hashCode()函数的值。仅当首次调用hashCode()方法时才计算哈希码值,然后缓存在此字段中。此外,哈希是使用String类的final字段进行一些计算生成的。因此,每次调用hashCode()方法时,都会得到相同的输出。对于调用者来说,似乎每次都在进行计算,但在内部它被缓存在哈希字段中。

String vs StringBuffer

由于在 Java 中 String 是不可变的,每当进行 String 操作如连接、子串等时,都会生成一个新的 String,并且将旧的 String 丢弃以进行垃圾收集。这些是繁重的操作,会在堆中生成大量垃圾。因此,Java 提供了StringBuffer 和 StringBuilder 类,用于字符串操作。StringBuffer 和 StringBuilder 是 Java 中的可变对象。它们提供了用于字符串操作的 append()、insert()、delete() 和 substring() 方法。

StringBuffer vs StringBuilder

StringBuffer在Java 1.4之前是对字符串进行操作的唯一选择。但是,它有一个缺点,即其所有公共方法都是同步的。StringBuffer提供了线程安全,但性能成本较高。在大多数情况下,我们不会在多线程环境中使用String。因此,Java 1.5引入了一个新的类StringBuilder,它与StringBuffer类似,除了线程安全和同步外。StringBuffer有一些额外的方法,比如substring、length、capacity、trimToSize等。然而,这些方法并不需要,因为在String中你也有这些方法。这就是为什么这些方法从未在StringBuilder类中实现的原因。StringBuffer是在Java 1.0中引入的,而StringBuilder类是在Java 1.5中引入的,之后查看了StringBuffer的缺点。如果你在单线程环境中,或者不关心线程安全,你应该使用StringBuilder。否则,对于线程安全的操作,应该使用StringBuffer。

StringBuilder与StringBuffer性能比较

I am trying to check the effect on performance because of synchronization with a sample program that performs append() on StringBuffer and StringBuilder object for multiple times.

package com.journaldev.java;

import java.util.GregorianCalendar;

public class TestString {

	public static void main(String[] args) {
		System.gc();
		long start=new GregorianCalendar().getTimeInMillis();
		long startMemory=Runtime.getRuntime().freeMemory();
		StringBuffer sb = new StringBuffer();
		//StringBuilder sb = new StringBuilder();
		for(int i = 0; i<10000000; i++){
			sb.append(":").append(i);
		}
		long end=new GregorianCalendar().getTimeInMillis();
		long endMemory=Runtime.getRuntime().freeMemory();
		System.out.println("Time Taken:"+(end-start));
		System.out.println("Memory used:"+(startMemory-endMemory));
	}
}

I ran the same code for the StringBuffer object also to check the time and memory values. I have executed the code 5 times for each case and then calculated the average values.

Value of i StringBuffer (Time, Memory) StringBuilder (Time, Memory)
10,00,000 808, 149356704 633, 149356704
1,00,00,000 7448, 147783888 6179, 147783888

很明显,即使在单线程环境下,StringBuilder的性能也比StringBuffer更好。这种性能差异可能是由于StringBuffer方法中的同步造成的。

String vs StringBuffer vs StringBuilder

  1. String是不可变的,而StringBuffer和StringBuilder是可变的类。
  2. StringBuffer是线程安全和同步的,而StringBuilder不是。这就是为什么StringBuilder比StringBuffer更快。
  3. String连接运算符(+)内部使用StringBuffer或StringBuilder类。
  4. 在非多线程环境中进行String操作时,我们应该使用StringBuilder,否则使用StringBuffer类。

这就是关于String、StringBuffer和StringBuilder之间区别的快速概述。在大多数一般编程场景中,StringBuilder比StringBuffer更适合。参考:

Source:
https://www.digitalocean.com/community/tutorials/string-vs-stringbuffer-vs-stringbuilder