1.StringBuffer与StringBuilder
StringBuffer类是一个为字符提供的可增大的缓冲区。我们在正常情况下要对一个string类型的句子进行添加,进行编码如下:
String ball="how";
ball=ball+"are";
ball=ball+"you";
这里面数组会反复复制,不断创建新的堆,影响性能,我们可以采用StringBuffer类完成同样的功能。
一些方法说明:
public class 缓冲区 {
public static void main(String[] args) {
StringBuffer sb =new StringBuffer();//同步 速度慢,安全,占空间大。
sb.append("123456789");//加入元素
System.out.println(sb.capacity());//缓冲区最初大小为16,超出后自动扩容为二倍(17--->34)
sb.insert(1,9);//插入元素 第一个参数代表插入元素放置的位置,第二个参数为插入元素的值
sb.delete(4,6);//删除一段区间里的元素 两个参数分别为删除区间端点,注意左闭右开(仅删除4,5号元素)
System.out.println(sb);
System.out.println(sb.indexOf("9"));//取出“9”所在位置的索引(只取最近的一个,取到一个即止),不存在返回-1
System.out.println(sb.indexOf("19"));//取出“19”所在位置的索引(从左往右看,多位数字取头),不存在返回-1
System.out.println(sb.lastIndexOf("8"));//从后往前看取出索引(多位数字视作整体查找,如“34”还是找“34”,而不是“43”)
System.out.println(sb.substring(2,6));//取出2-6区间里的数(都是闭区间)
StringBuilder sb2 =new StringBuilder();//不同步 快 不安全
sb2.append("");
}
}
两者的比较:
1. 在执行速度方面的比较:StringBuilder > StringBuffer
2. StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了。
3. StringBuilder:线程非安全的
StringBuffer:线程安全的
当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
拓展:Java中的String,StringBuilder,StringBuffer三者的区别
(1)运行速度。
运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。以下面一段代码为例:
1 String str="abc"; 2 System.out.println(str); 3 str=str+"de"; 4 System.out.println(str);
如果运行这段代码会发现先输出“abc”,然后又输出“abcde”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。另外,有时候我们会这样对字符串进行赋值
1 String str="abc"+"de"; 2 StringBuilder stringBuilder=new StringBuilder().append("abc").append("de"); 3 System.out.println(str); 4 System.out.println(stringBuilder.toString());
这样输出结果也是“abcde”和“abcde”,但是String的速度却比StringBuilder的反应速度要快很多,这是因为第1行中的操作和
String str="abcde";是完全一样的,所以会很快,而如果写成下面这种形式
1 String str1="abc"; 2 String str2="de"; 3 String str=str1+str2;
那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。
(2)线程安全
StringBuilder是线程不安全的,而StringBuffer是线程安全的。如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
(3)总结
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
2.包装类
基本数据类型不具有对象的特性,不能满足某些特殊的要求,如很多java类的方法参数都是Object类型的,而我们又需要这些类方法来处理基本类型的数据,就需要包装类。
java为我们提供了基本数据类型的包装类,这些包装类分为两类,一种是对象型包装类,不继承任何其他类(Object的直接子类),另一种是数值型包装类,继承于Number类。
包装类具有堆和栈,是”高级动物“,基本数据类型只有栈。
(1)基本数据类型对应的包装类如下:
(内容参考https://blog.csdn.net/weixin_40739833/article/details/80093527)
// boolean的包装类
public final class Boolean implements java.io.Serializable,Comparable<Boolean>
// char的包装类
public final
class Character implements java.io.Serializable, Comparable<Character>
// byte的包装类
public final class Byte extends Number implements Comparable<Byte>
// short的包装类
public final class Short extends Number implements Comparable<Short>
// int的包装类
public final class Integer extends Number implements Comparable<Integer>
// long的包装类
public final class Long extends Number implements Comparable<Long>
// float的包装类
public final class Float extends Number implements Comparable<Float>
// double的包装类
public final class Double extends Number implements Comparable<Double>
(2)拆箱与装箱
装箱:将基本数据类型封装为包装类对象,利用每一个包装类提供的构造方法实现装箱操作。
拆箱:将包装类中包装的基本数据类型数据取出。
简记——高级转低级:拆箱; 低级转高级:装箱。