草庐IT

StringBuffer与stringBuilder

Stuxinyan 2023-10-30 原文

StringBuffer与stringBuilder

对于String的学习:

final 修饰了String类所以String类是无法被修改的,并且不是基本数据类型。

当我们用双引号创建一个字符串时,jvm首先在字符串常量池中找寻具有相同值的字符串如果找到了,他将返回字符串常量池中的字符串对象引用。否则就在常量池中创建字符串对象并返回引用。

如果使用new创建字符串就需要在堆中创建它。

拼接字符串

我们使用Spring进行字符串拼接时,它会生成一个新的String并丢弃旧的String。/

这些操作肯定会在堆中产生大量垃圾冗余。于是产生了Stringbuffer(始于1.0之后)与StringBuilder(始于1.5之后)类用于对字符串的操作。
摘录自:https://developer.aliyun.com/article/787097?accounttraceid=7ccd1e5925ac4bff8b9d2ada96ac4f4arrjy
Java 中 String 与 StringBuffer 和 StringBuilder 的区别:
在 Java 1.4 之前,StringBuffer 是字符串操作的唯一选择。但是,它的一个缺点是所有公共方法都是同步的。 StringBuffer 提供线程安全性,但以性能为代价。
在大多数情况下,我们不会在多线程环境中使用 String。所以 Java 1.5 引入了一个新类 StringBuilder,除了线程安全和同步之外,它与 StringBuffer 类似。

StringBuffer 有一些额外的方法,例如 substring, length, capacity, trimToSize 等。但是,这些不是必需的,因为 String 中也有所有这些。这就是为什么这些方法从未在 StringBuilder 类中实现的原因。
StringBuffer 是在 Java 1.0 中引入的,而 StringBuilder 类是在查看 StringBuffer 的缺点后在 Java 1.5 中引入的。

假设在单线程环境中或无关线程安全,要使用 StringBuilder。反之,使用 StringBuffer 进行线程安全的操作。

关于Spring的面试体

//第一题
String s1 = "abc";
String s2 = "xyz";
String s3 = s1 + s2;
String s4 = "abc" + "xyz";
String s5 = "zbcxyz";
System.out.println(s3 == s4); // false
System.out.println(s4 == s5); // true

s1、s2都在常量池中,而s3=s1+s2,s3不会放在常量池中(只有字面常量才会放在常量池中),所以s3放在堆中,s4是两个字面常量拼接,所以会放在常量池中,内容为“abcxyz”,s5创建时,现在常量池中找到了相同的,所以两者引用相同

所以s3和s4的引用不同,s4和s5的引用相同
原文链接:https://blog.csdn.net/weixin_42193813/article/details/107725927

//第二种
String s1 = "abc";
String s2 = "xyz";
String s3 = s1 + s2;
String s4 = s3.intern();
String s5 = "abcxyz";
System.out.println(s3 == s4); // true
System.out.println(s4 == s5); // true

使用intern方法如果常量池中没有,则把对象复制一份(或对象引用)放入常量池中, 返回常量池中的对象,如果常量池中存在,则直接返回。
JDK1.7之前是复制一份放入常量池,JDK1.7之后则把对象引用到常量池。

intern方法:

intern() 方法返回字符串对象的规范化表示形式。
它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
String str1="aaa";
String str2=new String("aaa");
System.out.println(str1==str2);//false
System.out.println(str1==str2.intern());//true

s3存放在堆中,而创建s4时发现常量池中没有,则把s3对象复制一份放入常量池中(此时常量池中存放s3在堆中创建的“abcxyz”的地址),然后返回常量池中的对象,所以s3和s4指向同一个地址引用,结果为true

当创建s5时,发现常量池中有“abcxyz”地址,所以s5指向常量池中的地址,然后此地址再指向堆中“abcxyz”,所以s4和s5都指向常量池中的地址,结果为true

1、StringBuffer

在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。

String bufffer的方法:

序号方法描述
1public StringBuffer append(String s) 将指定的字符串追加到此字符序列。
2public StringBuffer reverse() 将此字符序列用其反转形式取代。
3public delete(int start, int end) 移除此序列的子字符串中的字符。
4public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。
5insert(int offset, String str) 将 str 参数的字符串插入此序列中。
6replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。
序号·常用方法描述
1int capacity() 返回当前容量。
2char charAt(int index) 返回此序列中指定索引处的 char 值。
3void ensureCapacity(int minimumCapacity) 确保容量至少等于指定的最小值。
4void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符从此序列复制到目标字符数组 dst
5int indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。
6int indexOf(String str, int fromIndex) 从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。
7int lastIndexOf(String str) 返回最右边出现的指定子字符串在此字符串中的索引。
8int lastIndexOf(String str, int fromIndex) 返回 String 对象中子字符串最后出现的位置。
9int length() 返回长度(字符数)。
10void setCharAt(int index, char ch) 将给定索引处的字符设置为 ch
11void setLength(int newLength) 设置字符序列的长度。
12CharSequence subSequence(int start, int end) 返回一个新的字符序列,该字符序列是此序列的子序列。
13String substring(int start) 返回一个新的 String,它包含此字符序列当前所包含的字符子序列。
14String substring(int start, int end) 返回一个新的 String,它包含此序列当前所包含的字符子序列。
15String toString() 返回此序列中数据的字符串表示形式。

2、StringBuilder

StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

我们来看一段代码及分析:

public class RunoobTest{
    public static void main(String args[]){
        StringBuilder sb = new StringBuilder(10);
        sb.append("Runoob..");
        System.out.println(sb);  
        sb.append("!");
        System.out.println(sb); 
        sb.insert(8, "Java");
        System.out.println(sb); 
        sb.delete(5,8);
        System.out.println(sb);  
    }
}
sb.append("Runoob..");  
 sb.append("!");
  sb.insert(8, "Java");
  sb.delete(5,8);
StringBuilder sb = new StringBuilder();
// 对象名.length() 序列长度
System.out.println(sb.length());  // 0
// 对象名.append() 追加到序列
sb.append("hello");
System.out.println(sb);  // hello
// 97代表的是是'a'
sb.appendCodePoint(97);
System.out.println(sb);  // helloa
// 链式编程
sb.append(1).append("world").append(2);
System.out.println(sb);  // helloa1world2
// 索引是5的位置替换成空格
sb.setCharAt(5, ' ');
System.out.println(sb);  // hello 1world2
// 指定位置0前插入0
sb.insert(0, 0);
System.out.println(sb);  // 0hello 1world2
// 删除索引6(包含)至索引14(不包含)的字符串
sb.delete(6, 14);
System.out.println(sb);  // 0hello
// StringBuilder类型转换成String类型
String s = sb.toString();
System.out.println(s);  // 0hello
// 以及还有截取、反转、替换等方法

总结

  • String 是不可变的,而 StringBuffer 和 StringBuilder 是可变类。
  • StringBuffer 是线程安全和同步的,而 StringBuilder 不是。这就是 StringBuilder 比 StringBuffer 快的原因。
  • 字符串连接运算符 (+) 在内部使用 StringBuilder 类。
  • 对于非多线程环境中的字符串操作,我们应该使用 StringBuilder 否则使用 StringBuffer 类。

有关StringBuffer与stringBuilder的更多相关文章

  1. ruby - 为什么 Ruby 没有真正的 StringBuffer 或 StringIO? - 2

    我最近读了一篇不错的post关于在Ruby中使用StringIO。不过,作者没有提到的是StringIO只是一个“I”。没有“哦”。你不能这样做,例如:s=StringIO.newsshouldbe"foo\nbar"#=>reallyis''`Ruby确实需要一个StringBuffer,就像Java那样。StringBuffers有两个重要的用途。首先,它们让您测试Ruby的StringIO所做的一半输出。其次,它们对于从小部分构建长字符串很有用——Joel一遍又一遍地提醒我们,否则会非常非常慢。有好的替代品吗?的确,Ruby中的字符串是可变的,但这并不意味着我们应该始终依赖该功能

  2. java - StringBuilder 和 ResultSet 性能问题的可能原因是什么 - 2

    我正在用Java循环遍历结果集;出于测试目的,它返回大约30行,每行17列(所有字符串数据)。我正在使用StringBuilder从结果中手动构建一个XML字符串,并且循环完成这些迭代实际上需要大约36秒。注意:我意识到这不是从数据库中获取XML的最佳方式,甚至不是从结果集中获取XML的最佳方式-但无论如何这都让我对缓慢的性能感到好奇。更新:根据目前的回复,我必须解决以下问题:运行查询的时间不到一秒,我在代码的每个部分前后都执行了System.currentTimeMillis()以缩小范围。36秒完全在下面的代码中。ResultSetMetaDatarsmeta=rset.getMe

  3. C# 从 StringBuilder 解析 Xml - 2

    我有一个包含XML文件内容的StringBuilder。在XML文件中有一个名为的根标签。并包含多个标签。我想通过XML进行解析以读取s中的标签值,但不确定该怎么做。我必须为此使用一些C#XML数据类型吗?提前致谢 最佳答案 StringBuildersb=newStringBuilder(xml);TextReadertextReader=newStringReader(sb.ToString());XDocumentxmlDocument=XDocument.Load(textReader);varnodeValueList=f

  4. c# - StringBuilder 还是 XMLDocument? - 2

    我编写了一个控制台应用程序来从Web服务器获取一些信息,将其转换为XML并保存。我手动创建了XML(使用StringBuilder附加字符串)。由于XML可能非常大,就内存而言,使用StringBuilder或XMLDocument类等更好吗?准确地说,我的问题是,如果XML类似于10mb文本,使用StringBuilder.append("")或System.XML命名空间是否具有内存效率?我认为更有效的方法是使用StringBuilder,但在每次迭代后将XML保存到HD上的文件并清除stringbuilder对象。任何意见?提前致谢。:) 最佳答案

  5. c# - StringBuilder 与 XmlTextWriter - 2

    我正在尝试从提供Xml内容的自定义HttpHandler中尽可能多地发挥性能。我想知道哪个对性能更好。使用XmlTextWriter类或临时StringBuilder操作,例如:StringBuildersb=newStringBuilder("");sb.AppendFormat("{0}",SOMEVALUE);有没有人有第一手经验? 最佳答案 正如Josh所说,这是一个微优化,如果您还没有证明它的必要性,您甚至不应该考虑它。它也确实不难测试:staticvoidMain(string[]arguments){constinti

  6. c# - 是否有人围绕 StringBuilders 或 Streams 实现了 Regex 和/或 Xml 解析器? - 2

    我正在构建一个压力测试客户端,它使用客户端可以召集的尽可能多的线程来攻击服务器并分析响应。我经常发现自己受到垃圾收集(和/或缺乏垃圾收集)的限制,在大多数情况下,它归结为我实例化的字符串,只是为了将它们传递给Regex或Xml解析例程。如果反编译Regex类,您会看到在内部,它使用StringBuilder来做几乎所有事情,但您不能传递给它一个字符串生成器;它有助于在开始使用之前深入研究私有(private)方法,因此扩展方法也不会解决它。如果您想从System.Xml.Linq中的解析器中获取对象图,您会遇到类似的情况。这不是迂腐的提前过度优化的情况。我看过Regexreplacem

  7. c# - 在 C# 中,检查 stringbuilder 是否包含子字符串的最佳方法 - 2

    我有一个现有的StringBuilder对象,代码向它附加了一些值和一个分隔符。我想修改代码以添加逻辑,在附加文本之前,它将检查它是否已存在于StringBuilder中。如果没有,它只会追加文本,否则将被忽略。这样做的最佳方法是什么?我需要将对象更改为string类型吗?我需要不会影响性能的最佳方法。publicstaticstringBuildUniqueIDList(contextRequestContext){stringrtnvalue=string.Empty;try{StringBuilderstrUIDList=newStringBuilder(100);for(int

  8. c# - 如何实现 StringBuilder 和/或调用 String.FastAllocateString? - 2

    我很想知道我是否可以创建一个优化版本的StringBuilder(尝试稍微加快它的速度,因为它目前是我的一个应用程序的瓶颈)。对我来说不幸的是,它似乎利用了我无法使用(或者看起来如此)的“神奇”系统调用。反编译System.Text.StringBuilder的源代码后,我注意到它使用了以下内部(因此无法调用)系统调用:[SecurityCritical][MethodImpl(MethodImplOptions.InternalCall)]internalstaticstringFastAllocateString(intlength);还有这个未记录的属性被大量使用:[ForceT

  9. c# - 从异步方法将字符串添加到 StringBuilder - 2

    我有返回字符串的异步方法(来自网络)。asyncTaskGetMyDataAsync(intdataId);我有:Task[]tasks=newTask[max];for(inti=0;i如何将每个任务的结果附加到StringBuilder?我想知道怎么做A)按照任务创建的顺序B)为了完成任务我该怎么做? 最佳答案 A)InorderoftaskcreationTask[]tasks=newTask()[max];for(inti=0;iB)InorderthattasksfinishTask[]tasks=newTask()[ma

  10. c# - 是否有 System.Text.StringBuilder 的二进制等价物? - 2

    我在C#中连接大量byte[]数组。如果我对字符串执行此操作,我会使用StringBuilder——是否有适用于byte[]数组中的二进制数据的等效类? 最佳答案 我不认为有一个完全等价的东西,但你可以用BinaryWriter来完成它:http://msdn2.microsoft.com/en-us/library/system.io.binarywriter.aspxMemoryStreamm=newMemoryStream();BinaryWriterwriter=newBinaryWriter(m);writer.Write

随机推荐