java关于字符串类的问题
String类和StringBuffer、StringBuild类的不同之处?
- 可以从对象变与不变和线程安全性考虑。
java既然有了String类,设计者为什么还要设计StringBuffer和StringBuild类呢?
-
引入话题
String a="a"; String b="b"; String c="c"; String d="d"; String abcd=a+b+c+d;
- 分析代码
- 以上代码实现的是得到关于a,b,c,d四个对象得拼接对象,这种拼接过程中,首先执行a+b操作,产生了ab字符串,然后加上c,又产生了abc字符串,最后加上d才得到abcd的String对象。由以上的示例可以看出,通过String直接相加来拼接字符串的效率是很低的,其中可能会产生多余的String对象,例如ab,abc。如果程序中需要拼接的字符串成千上万,那么对于jvm的负荷是相当大的,严重影响到程序的性能。
- 为了改进以上缺点,让其在拼接过程中减轻jvm的负荷,这是创造了StringBuffer类
- 分析代码
-
进展话题
StringBuffer s = new StringBuffer(); s.append(a); s.append(b); s.append(c); s.append(d); String abcd = s.toString(); System.out.println(abcd);
- 分析代码
- 上例是通过StringBuffer来拼接字符串的,可以看出它拼接过程中只产生一个对象,如果要拼接成千上万个字符,那么将会大大节省jvm的负荷
- 但是这种类有一个明显问题,那就是【线程不安全】,为了解决这个问题,产生了StringBuffer类来弥补。
- 分析代码
-
进一步话题
StringBuilder s= new StringBuilder(); s.append(a); s.append(b); s.append(c); s.append(d); String abcd =s.toString(); System.out.println(abcd);
- 分析代码
- 上面问题,基本解决了字符串拼接的缺点。
- 分析代码
-
总结:一般单线程使用了StringBuffer,一般实际线程安全时使用StringBuilder.
StringBuffer有哪些常用方法?
-
StringBuffer和StringBuilder方法基本一样。
-
常用方法介绍
-
存储
-
append():将指定数据作为参数添加到已有数据结尾处。
-
insert(index,数据):可以将数据插入到指定index位置,插入位置处后移。
StringBuffer s=new StringBuffer("Holle_Word"); s.insert(5, 123); System.out.println(s);
-
结果
Holle123_Word
-
-
删除
-
StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end。
StringBuffer s=new StringBuffer("Holle_Word"); s.delete(0, 5); System.out.println(s);
_Word
-
StringBuffer deleteCharAt(index):删除指定位置的字符。
-
-
获取
- indexOf():反回出字符串中位于的具体位置,如果没有,返回-1;下标从零开始。
- charAt():返回此序列中指定索引处的char值。
-
修改
-
setCharAt():该方法的作用是修改对象中索引值为index位置的字符为新的字符。
StringBuffer s=new StringBuffer("Holle_Word"); s.setCharAt(4, 'E'); System.out.println(s);
HollE_Word
-
replace(start,end,string):包括左边,不包括右边。
-
-
反转
- reverse();
-
字符串类StringBuffer和StringBuilder叫字符串类缓冲区,缓冲区体现在什么地方?
- 由于Java的String都是以定长的方式存储在内存中的,所以所有对String的增删改操作,都需要创建新的内存并进行内存复制。StringBuffer和StringBuilder的处理方式则与普通的String增删改有所不同,它们是先申请内存,从而避免频繁的内存申请。比如我们分接"a",“b”,“c”。如果通过"a" + “b” + “c"这种方式,(在没有优化的情况下)Java会先申请一个两字节的内存,将"a"和"b"复制到这个内存上,之后再申请一个三字节的内存,将"ab"和"c"复制到这块内存中。而通过StringBuffer或者StringBuilder,他们会先申请一块大内存(默认是十六字节),当我们拼接时,只需要直接复制"a”,“b”,"c"到这块内存上即可,不需要反复申请内存了。这里先申请后使用的形式就体现了缓冲区的概念。
- 打印StringBuffer,String,StringBuilder为什么要toString 输出结果不是一样的吗?
- 可以不用toString。直接打印StringBuffer实际上会自动调用toString,所以效果是一样的。