七、String、StringBuilder、StringJoiner的应用及相关类的底层原理

1 String字符串类:所有字符串字面值(如"abc")都是String类的实例实现

字符串是常量,一旦被创建就不能被改变!

字符串缓冲区支持可变的字符串,因为String对象是不可变的,所以可以共享

1.1 直接赋值与new的比较

使用双引号直接赋值时,系统检测该字符串在串池(StringTable)里是否存在(串池在堆内存中),不存在则创建新的,存在则复用

String s1 = "abc";    //串池中没有"abc",则会在内开辟一个空间存储"abc"(0x0011)

String s2 = "abc";    //串池中已经有"abc"(0x0011)

String s3 = new String("abc");    //只要有new,就会在堆内存中开辟空间(0x0022)
    
String s4 = new String("abc");    //只要有new,就会在堆内存中开辟空间(0x0033)

Scanner sc = new Scanner(System.in);

String s5 = sc.next();    //键盘录入相当于new出来的,会在堆内存中开辟空间(0x0044)

综上所述:

使用String s1 = "abc"直接赋值比String s3 = new String("abc")节省空间

1.2 根据索引返回对应字符

注意获得字符串长度是方法需要加括号:str.length()

数组获取长度是属性,不用加括号:arr.length

String str="abckscho";
for(int i=0;i<str.length();i++){
    char c=str.charAt(i);
    System.out.print(c);
}

1.3 利用ASCII码表让字符返回为数字

String id="411303200401100344";
char gender=id.charAt(16);
int num=gender-48;    //字符在参与运算时自动转换为ASCII码表所对应的数字

注意:char类型的变量在参与计算时类型自动提升为int,查询ASCII码表

public static void count(String str){
        int smallCount=0;
        int bigCount=0;
        int numberCount=0;
        for (int i = 0; i < str.length(); i++) {
            char c=str.charAt(i);
            if (c>='a'&&c<='z'){    //实际上是c字符对应的ASCII码值与a对应的ASCII码值相比较
                smallCount++;
            }else if (c>='A'&&c<='Z'){
                bigCount++;
            }else if (c>='0'&&c<='9'){    //实际上是c字符对应的ASCII码值与0对应的ASCII码值相比较
                numberCount++;
            }
}

1.4 字符翻转

public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.print("请输入一个字符串:");
        String str=sc.next();
        System.out.print(fanZhuan(str));
    }
public static String fanZhuan(String str){
    String result="";    //字符拼接
    for (int i = str.length()-1; i >=0; i--) {
        char c=str.charAt(i);    //使用charAt()获取每个位置上的字符
        result+=c;
    }
    return result;
}

1.5 截取字符串

substring(int beginIndex,int endIndex);    //截取[beginIndex,endIndex)
substring(int beginIndex);    //截取到末尾

1.6 字符替换str.replace("旧字符串","新字符串")

//获取说的话
String str="你玩的真好,下次不要再玩了,TMD";
//把TMD替换为***
String result=str.replace("TMD","***");
System.out.println(result);
//定义敏感词汇
String[] arr={"TMD","CNM","SB","MLGB"};
for (int i = 0; i < arr.length; i++) {
    str=str.replace(arr[i],"***");
}
System.out.println(str);

1.7 字符串转换为字符数组toCharArray(),字符数组转换为字符串

String str = "abcd";
char[] arr = str.toCharArray();    //arr[] = ['a','b','c','d']
String str2 = new String(arr)    //str2 = "abcd"

2 StringBuilder:一个容器,创建之后里面的内容可变

(1)构造方法

public SrtingBuilder( ),创建一个空白可变字符串对象,不含有任何内容

public SrtingBuilder( String str ),根据字符串内容创建可变字符串对象

(2)常用方法

sb.append(任意类型),添加数据,返回对象本身

sb.reverse( ),反转容器中的内容

sb.length( ),返回长度

sb.toString( ),把StringBuilder转换为String返回

 //创建对象
StringBuilder sb=new StringBuilder("123");
//添加元素
sb.append(124).append(true).append("abc");    //链式编程
//打印
System.out.println(sb);
//反转
sb.reverse();
System.out.println(sb);
//获取长度
System.out.println(sb.length());
//把StringBuilder变回字符串
String str=sb.toString();
System.out.println(str);
//判断字符串是否对称
Scanner sc=new Scanner(System.in);
System.out.print("请输入一个字符串:");
String str1=sc.next();
String str2=new StringBuilder().append(str1).reverse().toString();
if (str1.equals(str2)){
    System.out.println("对称");
    }else{
         System.out.println("不对称");
}

3 StringJoiner

(1)构造方法

public StringJoiner(间隔符号)

public StringJoiner(间隔符号,开始符号,结束符号)

(2)常用方法

sj.add(添加的内容),添加数据返回对象本身

sj.length( ),返回长度

sj.toString( ),把StringJoiner转换为String返回

//按指定格式拼接字符串
//方法一:使用StringBuilder
    public static void main(String[] args) {
        int[] arr={1,2,3};
        show(arr);
    }
    public static void show(int[] arr){
        StringBuilder str1=new StringBuilder().append("[");
        for (int i = 0; i < arr.length-1; i++) {
            str1.append(arr[i]).append(",");
        }
        String str2=str1.append(arr[arr.length-1]).append("]").toString();
        System.out.println(str2);
    }
//方法二:使用StringJoiner
        int[] arr={1,2,3};
        StringJoiner sj=new StringJoiner(",","[","]");
        for (int i = 0; i < arr.length; i++) {
           sj.add(arr[i]+"");
        }
        System.out.println(sj);

4 字符串相关类的底层原理

(1)字符串存储的内存原理

直接赋值复用字符串常量池中已有的字符串

new出来不会复用,而是开辟一个新的空间

(2)==号比较的内容

基本数据类型比较数据值

引用数据类型比较地址值,使用equals方法比较内容

(3)字符串拼接的底层原理

拼接时没有变量,会触发字符串优化机制,在编译时已是最终结果"abc"

String s1 = "a" + "b" +"c";    //java文件,记录在串池中的地址值
String s2 = "abc";    //class文件,复用串池中的字符串
System.out.println(s1 == s2);    //true

拼接时有变量,JDK8以前系统自动创建一个StringBuilder对象,然后调用append()完成拼接,拼接后调用toString()转换为String类型,而toString()底层原理是直接new了一个字符串对象。即:String s2 = s1 + "b"使用new StringBuilder()创建对象s2,s2.append("b").toString()使s2 = "ab",s3同理。

JDK8后,系统预估字符串拼接后的大小,把要拼接的内容都放在数组中,此后产生一个新的字符串

String s1 = "a";    //记录在串池中的地址值给s1
String s2 = s1 + "b";    //新new出来的对象
String s3 = s2 + "c";

(4)StringBuilder自动扩容分析

  • 默认创建一个长度为16的字节数组

  • 添加的内容<16,直接存

  • 添加的内容>16,扩容(原容量*2+2)

  • 扩容后还不够,则以实际长度为准

(5)StringBuilder提高效率原理分析

所有要拼接的内容都会放在StringBuilder中,不会创建很多无用的空间,节约内存

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L-Q-W

您的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值