JAVA篇08 —— String类

欢迎来到我的主页:【一只认真写代码的程序猿

本篇文章收录于专栏【小小爪哇

如果这篇文章对你有帮助,希望点赞收藏加关注啦~

目录

1 String概述

1.1 String特性

1.2 String常用方法

2 StringBuffer类

2.1 String与StringBuffer互转

2.2 StringBuffer常见方法

3 StringBuilder类

3.1 StringBuilder常用方法

3.2 三者使用比较


1 String概述

String对象用于保存字符串。

字符串常量对象用双引号括起来如"StringTest",Unicode编码,一个字符占两个字节。

常见构造器:new String();、new String(String original);、new String(char[] a);、new String(byte[] b)、new String(char[] a,int startIndex,int count);

    public static void main(String[] args) {
        String name = "jack";
        name = "jack1";
        final char[] value = {'j','a','k'};
        char[] v2 = {'j','a','c'};
        value[0] = 'a';
        //value = v2; 不可以修改 value 地址
    }

创建的两种方式:赋值和new String();

  • 赋值:先从常量池查看是否有"xxx"的数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址
  • new:先在堆中创建空间,里面维护了value属性,指向常量池的hsp空间如果常量池没有"hsp",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。


1.1 String特性

String是final类,字符串是不可变的,一个字符串对象一旦被分配,是不能改变的。

String s1 = "abc";
s1="bcd";//先创建"abc"常量字符串,再创建一个"bcd"字符串,让s1指向"bcd";
String a = "ab";//创建常量ab
String b = "cd";//创建常量cd
String c = a+b;//创建常量abcd

1.2 String常用方法

String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此提供StringBuilder 和 StringBuffer 来增强String的功能并提高效率。

  1. equls:区分大小写,内容是否相等。
  2. equalsIgnoreCase:忽略大小写判断内容是否相同。
  3. length:长度
  4. indexOf:字符在串中第一次出现的索引,从0开始,没有就返回-1.
  5. lastIndexOf:最后一次的索引。
  6. substring:截取指定范围的子串。
  7. trim:去掉前后空格。
  8. charAt:获取某个索引处的字符,不能用str[index]。
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "Hello";
        System.out.println("equals:" + str1.equals(str2));//false
        System.out.println("equalsIgnoreCase:" + str1.equalsIgnoreCase(str2));//true
        System.out.println("length:" + str1.length());//5
        System.out.println("indexOf(l):" + str1.indexOf('l'));//2
        System.out.println("lastIndexOf(l):" + str1.lastIndexOf('l'));//3
        System.out.println("substring(2):" + str1.substring(2));//llo
        System.out.println("substring(2,4):" + str1.substring(2, 4));//ll,是[2,4)

    }
  1. toUpperCase:全部转为大写
  2. toLowerCase:全部转为小写
  3. concat:字符串拼接,str1.concat(str2)
  4. replace:字符替换,str1.replace("orldStr","newStr");
  5. split:字符串切割,String strSplit [ ] = str.split(",");切割后是字符数组
  6. compareTo:字符串比较,str1比str2
  7. toCharArray:字符串转字符数组
  8. format:字符串格式化
    public static void main(String[] args) {
        //1. toUpperCase,转换成大写
        String str1 = "Hello";
        System.out.println(str1.toUpperCase());//HELLO
        //2. toLowerCase,转换成小写
        System.out.println(str1.toLowerCase());//hello
        //3. concat,拼接字符串
        String strConcat1 = "你好";
        String strConcat2 = ",我是xxx";
        System.out.println(strConcat1.concat(strConcat2));//你好,我是xxx
        //4. replace,替换字符
        //PS:replace方法返回的是替换后的字符串,原字符串不受影响。
        String strReplace = "你好,哈哈哈哈哈哈";
        String strRet = strReplace.replace("你好", "霓虹");
        System.out.println(strReplace);//你好,哈哈哈哈哈哈
        System.out.println(strRet);//霓虹,哈哈哈哈哈哈
        //5. split,对字符串进行分割,如果有特殊字符,需要加入转义字符“\”
        String poem = "床前明月光,疑是地上霜,举头望明月,低头思故乡";
        String splits[] = poem.split(",");
        for (String subStr : splits) {
            System.out.println(subStr);
            /*床前明月光
            疑是地上霜
            举头望明月
            低头思故乡*/
        }
        //特殊字符切割
        String local = "E:\\Test\\LocalCode\\result";//E:\Test\LocalCode\result
        System.out.println(local);
        String localSplit[] = local.split("\\\\");//因为一个"\\"表示一个"\",这里需要两对"\\"
        for (String subStr : localSplit) {
            System.out.print(subStr + " ");//E: Test LocalCode result
        }
        //6. toCharArray,转换成字符数组
        String s = "hello";
        char[] chs = s.toCharArray();
        for (int i = 0; i < chs.length; i++) {
            System.out.print(chs[i] + " ");//h e l l o
        }
        //7. compareTo 比较两个字符串大小
        //先比较单个字符:return c1-c2; 如果前面部分的内容相同,则return str1.len-str2.len
        String sct = "abcd";
        String sct2 = "accd";
        String sct3 = "abc";
        System.out.println(sct.compareTo(sct2));//b-c=-1
        System.out.println(sct.compareTo(sct3));//前面内容相同,返回len差是1

        /*8. format 格式字符串,类似于c语言输出
        占位符有:
        * %s 字符串 %c 字符 %d 整型 %.2f 浮点型
        */
        String name = "小明";
        int age = 10;
        double score = 66.6;
        char gender = '男';
        String formatStr = "我的姓名是%s 年龄是%d, 成绩是%.2f 性别是%c.大家好!";
        String Info = String.format(formatStr, name, age, score, gender);
        System.out.println(Info);


    }

2 StringBuffer类

java.lang.StringBuffer打表可变的字符序列,可以对字符串内容进行增删。很多方法与String相同,但是StringBuffer是可变长度。StringBuffer是个容器。

1. StringBuffer的直接父类是 AbstractStringBuilder

2. StringBuffer实现了Serializable, 即StringBuffer的对象可以串行化
3. 在父类中 AbstractStringBuilder 有属性 char[] value,不是 final,该value数组存放字符串内容,引出存放在堆中的。

4. StringBuffer是一个final类,不能被继承

5. 因为StringBuffer字符内容是存在 char[] value, 所有在变化(增加/删除)不用每次都更换地址(即不是每次创建新对象),所以效率高于String

创建:StringBuffer stringBuffer = new StringBuffer("hello");


2.1 String与StringBuffer互转

    public static void main(String[] args) {
        //String转StringBuffer
        String str = "hello nihao";
        //返回的才是 StringBuffer 对象, 对 str 本身没有影响
        //方法1:构造器
        StringBuffer stringBuffer = new StringBuffer(str);//hello nihao
        System.out.println("str=" + str);
        System.out.println("strBuffer=" + stringBuffer);
        //方法2:append方法
        StringBuffer stringBuffer1 = new StringBuffer();
        System.out.println("strBuffer1=" + stringBuffer1);//空串
        stringBuffer1 = stringBuffer1.append(stringBuffer);//hello nihao
        System.out.println("strBuffer1=" + stringBuffer1);

        //StringBuffer转String
        StringBuffer stringBuffer2 = new StringBuffer("hello 111");
        //方法1:StringBuffer的toString
        String string = stringBuffer2.toString();
        //方法2:构造器
        String string1 = new String(stringBuffer2);

    }

2.2 StringBuffer常见方法

  1. append( ):增。
  2. delete( ):删。
  3. replace( ):改。
  4. insert( ):插。
  5. indexOf( ):查。
public class StringBufferMethod {
    public static void main(String[] args) {
        StringBuffer s = new StringBuffer("hello");

        //增,append
        s.append(',');// "hello,"
        s.append("小明");//"hello,小明"
        s.append(",").append(100).append(true).append(10.5);
        System.out.println(s);//"hello,小明,100true10.5"

        //删
        //删除索引为>=start && <end 处的字符
        //删除 2~4 的字符 [2, 4)
        s.delete(2, 4);
        System.out.println(s);//"heo,小明,true10.5"

        //改
        //使用 王大大红 替换 索引 4-8 的字符 [4,8)
        s.replace(4, 8, "王大红");
        System.out.println(s);//"heo,王大红00true10.5"

        //插
        //在索引为 4 的位置插入 "小明和",原来索引为 4 的内容自动后移
        s.insert(4, "小明和");
        System.out.println(s);//"heo,小明和王大红00true10.5"

        //查
        //找指定的子串在字符串第一次出现的索引, 如果找不到返回-1
        int indexOf = s.indexOf("王大");
        System.out.println(indexOf);//4

        System.out.println("len=" + s.length());//20
    }
}

一些小源码:

/**
 * @ClassName StringBufferNullTest
 * @Description 一些StringBuffer的小案例
 * @Date 2024/12/1 10:32
 * @Version V1.0
 */
public class StringBufferNullTest {
    public static void main(String[] args) {
        String str = null;
        StringBuffer sb = new StringBuffer();//'StringBuffer sb' may be declared as 'StringBuilder'
        /*底层源码:
        @IntrinsicCandidate
        public StringBuffer() {
            super(16);
        }
        super源码是:
        AbstractStringBuilder(int capacity) {
            if (COMPACT_STRINGS) {
                value = new byte[capacity];
                coder = LATIN1;
            } else {
                value = StringUTF16.newBytesFor(capacity);
                coder = UTF16;
            }
        }
        */
        sb.append(str);
        System.out.println(sb.length());//4
        System.out.println(sb);//null
        //下面代码报异常:
        //Cannot invoke "String.length()" because "str" is null
        //    AbstractStringBuilder(String str) {
        //        int length = str.length();但是null没有方法可以调用
        StringBuffer sb1 = new StringBuffer(str);

//        System.out.println(sb1);
    }
}

一个小场景:

    public static void main(String[] args) {
        String price = "2746358998.98";
        StringBuffer sb = new StringBuffer(price);
        //将小数点前,每三位加一个逗号。如:2,746,358,998.98
        //1、找到小数点位置index,然后index-3
        for(int i=sb.lastIndexOf(".")-3;i>0;i-=3){
            sb=sb.insert(i,",");
        }
        System.out.println(sb);//2,746,358,998.98
    }

3 StringBuilder类

也是可变字符序列,提供了与StringBuffer兼容的API,答案是不保证同步(线程不安全),被设计为StringBuffer的简易替换,用在字符串缓冲区被单线程使用的时候。比StringBuffer要快。

主要操作是append和insert,可以重载以接收任意的数据类型。

1. StringBuilder 继承 AbstractStringBuilder 类 
2. 实现了 Serializable ,说明 StringBuilder 对象是可以串行化(对象可以网络传输,可以保存到文件) 3. StringBuilder 是 final 类, 不能被继承 
4. StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 char[] value; 因此, 字符序列是堆中 
5. StringBuilder 的方法, 没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用StringBuilder
6. StringBuilder stringBuilder = new StringBuilder();


3.1 StringBuilder常用方法

与StringBuffer一样,所以主要看看源码在干什么即可。


3.2 三者使用比较

StringBuffer和StingBuilder很类似,均是可变字符串,方法也一样。单线程用Builder。

String:不可变字符串,效率低,复用率高。

StringBuffer:可变字符串序列,效率较高,线程安全。

StingBuilder:可变字符串序列,效率最高但是线程不安全。

我们知道String的修改实际上是创建新的对象,导致产生大量的副本,性能低;所以,如果要对字符串做大量修改,不用String。

 效率比较:Builder > Buffer > String

package IntegerTest;

/**
 * @ClassName Effective
 * @Description 三者效率比较,拼接5w次字符串
 * @Date 2024/12/1 11:18
 * @Version V1.0
 */
public class Effective {
    public static void main(String[] args) {
        long starTime = 0L;
        long endTime = 0L;

        StringBuilder builder = new StringBuilder("");
        starTime = System.currentTimeMillis();
        for(int i=0;i<50000;i++){
            builder.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder拼接时间为:"+(endTime-starTime)+"ms");

        StringBuffer buffer = new StringBuffer("");
        starTime = System.currentTimeMillis();
        for(int i=0;i<50000;i++){
            buffer.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer拼接时间为:"+(endTime-starTime)+"ms");

        starTime = System.currentTimeMillis();
        String string = "";
        for(int i=0;i<50000;i++){
            string+=i;
        }
        endTime = System.currentTimeMillis();
        System.out.println("String 拼接时间为:"+(endTime-starTime)+"ms");
    }
}

 结论:如果字符串需要多次修改,单线程用Builder,多线程用Buffer;很少修改,被多个对象引用用String,如配置文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Echo-Nie

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值