StringBuilder
StringBuilder 概述
StringBuilder是一个可变字符串类,可以看做是一个容器。在java.lang包下,使用时不需要导包。和String有不同之处,String内容不可以改变,而SB可以改变。并且可以装任意数据类型例如int,char,string,long…
SB作用:提高字符串操作效率
例如:+拼接对比使用SB拼接。
public class Demo1StringBuilder {
public static void main(String[] args) {
testMethod();//793毫秒
long start = System.currentTimeMillis();
StringBuilder sB = new StringBuilder();
for (int i = 1; i <=50000 ; i++) {
sB.append(i);
}
long end = System.currentTimeMillis();
System.out.println(end - start);//2毫秒
}
/**ctrl+alt+M快速抽取方法得到testMethod()*/
private static void testMethod() {
//获取1970.1.1到当前时间锁经历过的毫秒值,1秒=1000毫秒;以long类型返回
long start = System.currentTimeMillis();
String s = "";
for (int i = 1; i <= 50000 ; i++) {
s += i;
}
System.out.println(s);
//获取1970.1.1到当前时间锁经历过的毫秒值,1秒=1000毫秒;以long类型返回
long end = System.currentTimeMillis();
//得到for循环运行时间
System.out.println(end - start);//793毫秒
}
}
SB的两个构造方法
空参构造方法:
空参构造public StringBuilder():创建一个可变字符串对象,不含任何内容
带参构造方法:
带参构造方法 public StringBuilder(String str):根据传入的参数,来创建可变字符串对象
public class Demo2StringBuilder {
public static void main(String[] args) {
//空参构造public StringBuilder()
StringBuilder SB = new StringBuilder();
System.out.println(SB);//结果为空
//带参构造方法 public StringBuilder(String str)
StringBuilder SB2 = new StringBuilder("abc");
System.out.println(SB2);//abc
}
}
SB的常用成员方法
append(任意类型)
public StringBuilder append(任意类型) //添加数据,返回对象本身
reverse()
public StringBuilder reverse() //返回相反的字符序列,即把字符串倒置过来
length()
public int length() //返回长度(字符出现的个数而不是字符串的个数)
toString()
public String toString() //通过toString()就可以实现把StringBuilder转换为String
例:
public class Demo3StringBuilder {
public static void main(String[] args) {
StringBuilder SB = new StringBuilder();
/**
public StringBuilder append(任意类型) //添加数据,返回对象本身
*/
/*SB.append(123);
System.out.println(SB);
SB.append(true);
System.out.println(SB);
SB.append("sef");
System.out.println(SB);
SB.append("abc");
System.out.println(SB);*/
// 123
// 123true
// 123truesef
// 123truesefabc
//以上代码证明StringBuilder 是一个可变的字符串
StringBuilder SB2 = new StringBuilder("ddd");
StringBuilder SB3 = SB2.append(123);
StringBuilder SB4 = SB3.append(true);
System.out.println(SB4);
/**
* 根据方法返回值可知,调用append以后返回的是它本身所以以上代码可以优化
* 链式编程:如果一个方法返回的是对象类型,那对象就可以继续向下调用方法。
* */
SB.append("ddd").append(123).append(true);
System.out.println(SB);
/**
* public StringBuilder reverse() //返回相反的字符序列,即把字符串倒置过来
* */
SB.reverse();
System.out.println("反转之后为" + SB);
/**
* public int length() //返回长度(字符出现的个数而不是字符串的个数)
* */
SB.length();
System.out.println("SB中字符个数为" + SB.length());
/**
* public String toString() //通过toString()就可以实现把StringBuilder转换为String
* */
String s = SB.toString();
System.out.println(s);
}
}
SB如何提高字符串处理效率(原理)?
字符串通过+拼接的原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aOnPk8Vu-1640432422260)(G:\Typora笔记\image-20211224161014987.png)]
以上代码在内存中如何运行?
//注意方法区并不在堆内存内,要区分开!
首先字节码文件Test.class会先加载进方法区,main主方法被虚拟机自动调用进入栈内存,之后开始执行第一句代码
String s1 = "a";
使用 双引号"" 创建字符串对象,会先检查字符串常量池里有没有,没有的话就创建。之后 s1 就会记录常量池中 "a" 的内存地址。
再往下 String s2 = s1 + "b";
在java中只要出现了 加号+ 拼接,系统底层就会自动在堆内存中创建一个SB对象
new StringBuilder();
然后还会自动调用该对象的append方法完成拼接,也就是"ab"。但是s2还没不能直接记录"ab"的地址,因为"ab"还是一个SB对象。所以系统还会自动调用SB的toString方法把SB类型转换为String类型。"ab"(StringBuilder,地址假设为001)->"ab"(String,地址为假设002)。
s2记录下地址002。
接着往下 String s3 = s2 +"c";
重复上面的判断创建和拼接过程,"abc"(StringBuilder,地址假设为003)->"abc"(String, 地址设为004),s3在这一步才能记录下004这份内存地址。
最后打印的s3就是004记录的abc。
结论:字符串的加号+拼接,只要出现一个+,堆内存中就会有两个对象(StringBuilder,String)
字符串通过SB拼接提高效率的原理[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jki82WlY-1640432422261)(G:\Typora笔记\image-20211224154825039.png)]
首先字节码文件Test.class会先加载进方法区,main主方法被虚拟机自动调用进入栈内存,之后开始执行第一句代码
StringBuilder sb = new StringBuilder();
堆内存中开辟一个空间产生地址001存储SB对象,sb记录001。
往下
sb调用append方法添加了"a","b","c"三个字符串,首先三个字符串会在字符串常量池存在,然后append方法会把它们在堆内存中完成拼接,这些拼接都在一个SB对象当中进行。
拼接完成后,再打印sb,就会打印出"abc"当然"abc"是一个 StringBuilder 对象,想得到一个 String 类型,通过手动调用该对象的toString方法即可。
使用SB对象进行字符串拼接,不论多少个字符串,在堆内存中只有一个对象,这就是SB提高效率的原理。
案例
需求1:
键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
对称字符串:123321、111
非对称字符串:123123
思路:
1. 键盘录入一个字符串,用 Scanner 实现
2. 将键盘录入的字符串反转
3. 使用反转后的字符串,和原字符串进行比对
4. 如果相同,则输出是对称字符串,反之输出不是对称字符串
StringBuilder转换为String
public String toString():通过toString()就可以实现把 StringBuilder转换为String
String转换为StringBuilder
public StringBuilder(String str):通过构造方法就可以实现把String转换为StringBuilder
public static void main(String[] args) {
// 1. 键盘录入一个字符串,用 Scanner 实现
Scanner sc = new Scanner(System.in);
System.out.println("请输入对称字符串:");
String s = sc.nextLine();
// 2. 将键盘录入的字符串反转
// 将字符串封装为StringBuilder对象, 目的是为了掉用其反转的方法
StringBuilder sb = new StringBuilder(s);
sb.reverse();
String reverseStr = sb.toString();
// s : String
// sb : StringBuilder
// 3. 使用反转后的字符串,和原字符串进行比对
if(s.equals(reverseStr)){
System.out.println("是对称字符串");
}else{
System.out.println("不是对称字符串");
}
}
}
### 需求2:
定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回
调用该方法,并在控制台输出结果。
例如,数组为int[] arr = {1,2,3};
执行方法后的输出结果为:[1, 2, 3]
思路:
1. 定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
2. 定义一个方法,返回值类型 String,参数列表 int[] arr
3. 在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
4. 调用方法,用一个变量接收结果
5. 输出结果
public static void main(String[] args) {
// 1. 定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
int[] arr = {1,2,3};
// 4. 调用方法,用一个变量接收结果
String s = arrayToString(arr);
// 5. 输出结果
System.out.println(s);
}
// 2. 定义一个方法,返回值类型 String,参数列表 int[] arr
public static String arrayToString(int[] arr){
// 3. 在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
if(i == arr.length -1){
sb.append(arr[i]).append("]");
}else{
sb.append(arr[i]).append(", ");
}
}
return sb.toString();
}
}
static关键字复习:
static的作用是,将属性或者方法修饰为该类的共享成员,即这个属性或方法是该类实例化的所有对象之间共享的,
不为某个实例对象所有,static属性或方法是存储在内存的公共区,
一个类中,一个static变量只会有一个内存空间,虽然有多个类实例,
但这些类实例中的这个static变量会共享同一个内存空间。
static的变量是在类装载的时候就会被初始化,即,只要类被装载,不管是否使用了static变量,都会被初始化。
static的基本规则
·一个类的静态方法只能访问静态属性
·一个类的静态方法不能直接调用非静态方法
·如访问控制权限允许,static属性和方法可以使用类名加“.”的方式调用,也可以使用实例加“.”的方式调用
·静态方法中不存在当前对象,因而不能使用this,也不能使用super
·静态方法不能被非静态方法覆盖
·构造方法不允许声明为static的
注,非静态变量只限于实例,并只能通过实例引用被访问。
小结:
java中主类中定义方法加static和不加static的区别
前者可以省略类名直接在主方法调用,后者必须先实例化后用实例调用