1. Overview
1.概述
String and StringBuffer are two important classes used while working with strings in Java. In simple words, a string is a sequence of characters. For example, “java”, “spring” and so on.
String 和 StringBuffer 是 Java 中处理字符串时使用的两个重要类。简单地说,字符串就是一串字符。例如,”java”、”spring “等。
The main difference between a String and a StringBuffer is that a String is immutable, whereas a StringBuffer is mutable and thread-safe.
字符串和字符串缓冲区之间的主要区别在于,字符串是不可变的,而字符串缓冲区是可变的,并且是线程安全的。
In this tutorial, let’s compare String and StringBuffer classes and understand the similarities and differences between the two.
在本教程中,我们将比较 String 和 StringBuffer 类,并了解两者的异同。</span
2. String
2.字符串 .
The String class represents character strings. Java implements all string literals, such as “baeldung”, as an instance of this class.
字符串类表示字符串。Java 将所有字符串字面量(如 “baeldung”)作为该类的实例来实现。
Let’s create a String literal:
让我们创建一个 String 字面:
String str = "baeldung";
Let’s also create a String object:
让我们也创建一个 String 对象:
Char data[] = {‘b’, ‘a’, ‘e’, ‘l’, ‘d’, ‘u’, ‘n’, ‘g’};
String str = new String(data);
We can also do the following:
我们还可以做到以下几点:
String str = new String(“baeldung”);
Strings are constants and immutable, making them shareable.
字符串是常量且不可变,因此可以共享。
2.1. String Literal vs. String Object
2.1.字符串字面与字符串对象
String literals are immutable strings that are stored inside a special memory space called a string pool inside the heap memory. Java doesn’t allocate a new memory space for string literals having the same value. Instead, it uses the string interning.
字符串字面量是不可变的字符串,存储在堆内存中称为字符串池的特殊内存空间中。Java 不会为具有相同值的字符串字面量分配新的内存空间。相反,它使用字符串互操作。
In contrast, the JVM allocates separate memory in the heap, outside the string pool, for a newly created String object.
相比之下,JVM 会在字符串池之外的堆中为新创建的字符串对象分配单独的内存。
Thus, each string object refers to a different memory address, even though both may have the same value. Note that a String literal is still a String object. However, the reverse is not true.
因此,每个字符串对象都指向不同的内存地址,尽管两者可能具有相同的值。请注意,String 字面仍然是一个 String 对象。但是,反之则不然。
2.2. String Pool
2.2.字符串池</b
String literals are stored in a reserved memory area of the Java heap called the String Pool.
字符串字面量存储在 Java 堆中名为字符串池的保留内存区域中。
2.3. String Interning
2.3.字符串互调</b
String interning is an optimization technique the compiler uses to avoid redundant memory allocation. It avoids allocating memory for a new string literal if a similar value already exists. Instead, it works with the existing copy:
字符串互调是编译器用来避免冗余内存分配的一种优化技术。如果已经存在类似的值,编译器就不会为新的字符串字面量分配内存。相反,它会使用现有的副本:
Common operations on String include concatenation, comparison, and searching. The Java language also provides special support for the string concatenation operator (+) and for the conversion of other objects to strings. It is worth noting that String internally uses StringBuffer and its append method to perform concatenation:
对 String 的常用操作包括连接、比较和搜索。Java 语言还为字符串连接操作符 (+) 和将其他对象转换为字符串提供了特殊支持。值得注意的是,String 内部使用 StringBuffer 及其 append 方法来执行连接:
String str = "String";
str = str.concat("Buffer");
assertThat(str).isEqualTo("StringBuffer");
assertThat(str.indexOf("Buffer")).isEqualTo(6);
3. StringBuffer
3. StringBuffer
A StringBuffer is a sequence of characters just like a String. However, unlike a String, it’s mutable. We can modify a StringBuffer through method calls such as append() and insert(). The append method adds the character sequence at the end of the StringBuffer, while the insert method inserts a sequence of characters at a specified index. The StringBuffer class has both methods overloaded to handle any object. The object is converted to its string representation before appended or inserted into the StringBuffer:
StringBuffer和String一样,都是字符序列。 我们可以通过调用 append() 和 insert() 等方法来修改 StringBuffer 。append 方法在 StringBuffer 的末尾添加字符序列,而 insert 方法则在指定索引处插入字符序列。StringBuffer 类重载了这两种方法,以处理任何对象。在向 StringBuffer 追加或插入对象之前,先将对象转换为其字符串表示形式: StringBuffer class has both methods overloads to handle any object.
StringBuffer sBuf = new StringBuffer("String");
sBuf.append("Buffer");
assertThat(sBuf).isEqualToIgnoringCase("StringBuffer");
sBuf.insert(0, "String vs ");
assertThat(sBuf).isEqualToIgnoringCase("String vs StringBuffer");
StringBuffer is thread-safe and can work in a multi-threaded environment. The synchronization ensures the correct order of execution of all statements and avoids data-races situations.
字符串缓冲区是线程安全的,可以在多线程环境中工作。同步确保了所有语句的正确执行顺序,并避免了数据竞赛情况。
However, Java 1.5 introduced StringBuilder as an alternative to StringBuffer for performance optimization in situations where thread safety is not a concern. It’s recommended to use StringBuilder in places where the string buffer is being used by a single thread, as it will be faster under most implementations.
但是,Java 1.5 引入了StringBuilder,作为 StringBuffer 的替代,用于在不考虑线程安全的情况下优化性能。建议在单线程使用字符串缓冲区的情况下使用 StringBuilder,因为它在大多数实现中都会更快。
4. Performance Comparison
4.性能比较</b
String and StringBuffer have similar performance. However, string manipulation is faster with StringBuffer than String because String requires the creation of a new object each time, and all changes happen to the new String, leading to more time and memory consumption.
String 和 StringBuffer 的性能相似。但是,使用 StringBuffer 操作字符串比使用 String 更快,因为 String 每次都需要创建一个新对象,而且所有更改都发生在新的 String 中,这将导致更多的时间和内存消耗。
Let’s do a quick micro-benchmark with JMH to compare the concatenation performance of String and StringBuffer:
让我们使用 JMH 快速进行微基准测试,比较 String 和 StringBuffer 的连接性能:
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Measurement(batchSize = 100000, iterations = 10)
@Warmup(batchSize = 100000, iterations = 10)
@State(Scope.Thread)
public class ComparePerformance {
String strInitial = "springframework";
String strFinal = "";
String replacement = "java-";
@Benchmark
public String benchmarkStringConcatenation() {
strFinal = "";
strFinal += strInitial;
return strFinal;
}
@Benchmark
public StringBuffer benchmarkStringBufferConcatenation() {
StringBuffer stringBuffer = new StringBuffer(strFinal);
stringBuffer.append(strInitial);
return stringBuffer;
}
}
Benchmark Mode Cnt Score Error Units
ComparePerformance.benchmarkStringBufferConcatenation ss 10 16.047 ± 11.757 ms/op
ComparePerformance.benchmarkStringConcatenation ss 10 3.492 ± 1.309 ms/op
5. Comparison Table
5.对比表</b
To summarise the differences:
总结一下不同之处:
String | StringBuffer |
A String is a sequence of characters and is immutable | A StringBuffer is like a String but can be modified, i.e., it’s mutable |
It can be shared easily due to its immutability | It can be shared across synchronized threads only |
Modification requires the creation of a new string | Modification requires a call to certain methods |
Modification is slow | Modification is faster |
It uses the string pool for storing data | It uses heap memory |
6. Conclusion
6.结论</b
In this article, we compared String and StringBuffer classes. As always, the example code is available over on GitHub.
在本文中,我们比较了 String 和 StringBuffer 类。一如既往,示例代码可在 GitHub上获取。