你好!ð¼
本文将是关于我们在Java及其替代方案(StringBuilder and StringBuffer)中经常使用的字符串类。我可能会错过,跳过或无意中传达的观点。如果您在这种情况下通过电子邮件给我反馈,我会很高兴。
现在,让我们开始开始
1.弦
首先,让我们看字符串类。众所周知,字符串类是代表字符数组的Java中的复杂数据类型之一。该课程存储了一系列字符,并提供了来操纵这些字符的多个功能。当我们要使用它时,我们将其定义如下所示并分配一个值。
String str= "Merhaba";
到目前为止,这里没有问题。但是,正如我们所知,在Java中, string 类是“ 不变”,这意味着它无法更改。但是,当然,有些人可能会说:“ 哦,不,我已经更改并分配了很多次,并执行了我想要的操作!”
这是促使我写这篇文章的情况。
实际上,当我们操纵字符串变量时,变量点不更改ð的值。在这样的操作中,在堆中打开了一个新的空间,并将操纵值放置在那里,我们对这个新地址的参考点。
String str = "Merhaba";
str.concat("Dünya");
如上图所示,当我们定义时,然后执行“ concat ”操作,如前所述,在内存中创建了一个新的空间,而我们的“ str ”现在可变引用“ merhabadã¼nya”的地址。
因此,每次操纵变量时,都会在内存中不断打开一个新的空间。当然,这不是我们想要的,因为它会导致性能和时间损失。 ð
在这一点上, stringBuilder 班级都得到了我们的帮助。
2.StringBuilder
stringBuilder 的作用也与 string 相同。它代表字符字符串。但是,与字符串的区别在于,它是“ Mutable ”或可变类。因此,它比 string 类更好的选择是一个更好的选择。
例如,如果我们想将文本文件中的所有单词转换为大写,则 stringBuilder class可以轻松地执行此操作,而无需在内存中重新创建整个文本(字符串正在创建一个新的空间此新值的内存)。
或一个非常简单的示例,例如下面的一个。
StringBuilder sentence = new StringBuilder("This is a sentence.");
sentence.append("Added word.");
System.out.println(sentence.toString()); //This is a sentence.Added word.
但是,该类别尚未提及的重要缺点,这是其缺乏线程安全结构。如果要使用涉及线程的过程,则在这种情况下, StringBuilder 类不适合。可以使用以下代码段来解释此限制:
StringBuilder sb = new StringBuilder();
Thread t1 = new Thread(() -> {
for(int i=0; i<10000; i++){
sb.append("A");
}
});
Thread t2 = new Thread(() -> {
for(int i=0; i<10000; i++){
sb.append("B");
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(sb.toString());
在此示例中,两个不同的线程, t1 和 t2 ,访问 stringBuilder 对object object object object 同时访问字符“ a”和“”字符。 b“以连续方式分别为10,000次。但是,由于 StringBuilder 对象缺乏同步,因此所得的输出是不确定的,并且每次执行都可能产生不同的结果。本质上,引入了数据竞赛条件。
要解决此问题,我们可以使用 StringBuffer 类。
3. StringBuffer
我不会在此处重复使用StringBuffer的相同信息,如果您已经阅读了这么远,您已经可以猜测,此类的唯一区别是其“线程安全”或同步结构。它具有与StringBuilder相同的方法和逻辑。
但是,这个伟大的功能也带来了一些缺点。它的同步结构使其工作速度比StringBuilder慢。
如果我们尝试用小型代码段解释此内容,
public class StringBufferVsStringBuilder {
public static void main(String[] args) {
int N = 1000000;
long startTime, endTime, duration;
// StringBuffer performance test
StringBuffer buffer = new StringBuffer();
startTime = System.nanoTime();
for (int i = 0; i < N; i++) buffer.append("hello");
endTime = System.nanoTime();
duration = (endTime - startTime);
System.out.println("Time taken by StringBuffer: " + duration + " nanoseconds");
//Time taken by StringBuffer: 19494000 nanoseconds
// StringBuilder performance test
StringBuilder builder = new StringBuilder();
startTime = System.nanoTime();
for (int i = 0; i < N; i++) builder.append("hello");
endTime = System.nanoTime();
duration = (endTime - startTime);
System.out.println("Time taken by StringBuilder: " + duration + " nanoseconds");
//Time taken by StringBuilder: 17145000 nanoseconds
}
}
此代码计算 StringBuilder 和 stringBuffer 的经过的时间,以将单词“ hello> hello ”添加一百万次。当我们运行此代码时,我们可以轻松地观察到 StringBuffer 由于其同步结构而起作用较慢。通过增加n。
的价值,我们可以使这种差异更加突出。作为摘要,我在下表中添加了两个类的功能,
功能 | stringbuilder | stringBuffer |
---|---|---|
线程安全 | 否 | 是 |
性能 | 快速 | 慢 |
内存使用 | 少 | 更多 |
可变 | 是 | 是 |
最后,
- 使用字符串类没有任何伤害,但是我们应该记住它是不变的,每次我们尝试修改它时, 都会创建一个新的内存空间< /strong>。
- 另一方面, StringBuilder 执行所有操作而无需创建新的内存空间,但是由于它没有同步结构,因此它可能会在含线的应用程序中提供不正确的结果。
- 我们可以通过使用 stringBuffer 来解决 stringBuilder 的问题,该在同步结构中运行,但是与 stringbuilder相比,此类可能会导致某些性能损失。 /strong>。
如果您花了一些时间阅读了这篇文章,请非常感谢。如果您发现任何错误,请随时通过电子邮件与我联系。
对于原始文章 - > https://bayten.dev/posts/string-stringbuilder-and-stringbuffer-in-java/
愉快的编码! ð
p>
p>
参考
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StringBuffer.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StringBuilder.html
- https://www.digitalocean.com/community/tutorials/string-vs-stringbuffer-vs-stringbuilder