• String、StringBuffer、StringBuilder的区别


    String、StringBuffer、StringBuilder的区别

    1. String 类

    • String 对象用于保存字符串,也就是一组字符序列
    • 字符串常量对象使用**双引号(" ")**括起的字符序列。例如:“xjz”、"2002"等
    • 字符串的字符使用Unicode编码,一个字符(不区分字母还是汉字)占两个字节
    • String类较常用构造器(其他看手册)
    String s1 = new String();
    String s2 = new String(String original);
    String s3 = new String(char[] a);
    String s4 = new String(char[] a,int startIndex,int count);
    
    • 1
    • 2
    • 3
    • 4

    image-20230912100346685

    1.1 创建String对象的两种方式

    1. 方式一:直接赋值 String s = “xjz2002”;
    2. 方式二:调用构造器 String s2 = new String(“xjz2002”);
    • 方式一:先从常量池查看是否有"xjz2002"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址

    • 方式二:现在堆中创建空间,里面维护了value属性,指向常量池的xjz2002空间。如果常量池中没有"xjz2002",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。

    • 画出两种方式的内存分布

      image-20230912101838202

    1.2 String 类的常见方法

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

    image-20230912102045439

    package com.xjz.string;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class StringMethod01 {
        public static void main(String[] args) {
    
            //1. equals 前面已经讲过了,比较内容是否相同,区分大小写
            String str1 = "hello";
            String str2 = "Hello";
            System.out.println(str1.equals(str2)); //False
    
            //2. equalsIgnoreCase 忽略大小写的判断内容是否相等
            String username = "johN";
            if ("john".equalsIgnoreCase(username)){
                System.out.println("Success!");
            } else {
                System.out.println("Failure!");
            }
    
            //3. length 获取字符的个数,字符串的长度
            System.out.println("徐金卓".length());
    
            //4. indexOf 获取字符在字符串对象中第一次出现的索引,索引从 0 开始,如果找不到,返回 -1
            String s1 = "wer@terwe@g";
            int index = s1.indexOf('@');
            System.out.println(index); //3
            System.out.println("weIndex = " + s1.indexOf("we")); //0
    
            //5. lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从 0 开始,如果找不到,返回 -1
            s1 = "wer@terwe@g@";
            index = s1.lastIndexOf('@');
            System.out.println(index);//11
            System.out.println("ter 的位置=" + s1.lastIndexOf("ter"));//4
    
            //6. substring 截取指定范围的子串
            String name = "hello,张三";
            //下面 name.substring(6) 从索引 6开始截取后面所有内容
            System.out.println(name.substring(6));
    
            //下面 name.substring(2,5) 从索引 2 开始,截取到 4 即llo
            //左闭右开区间 [2,5)
            System.out.println(name.substring(2,5));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    image-20230912102305625

    package com.xjz.string;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class StringMethod02 {
        public static void main(String[] args) {
    
            //1. toUpperCase 转换成大写
            String s = "heLLo";
            System.out.println(s.toUpperCase()); //HELLO
    
            //2. toLowerCase
            System.out.println(s.toLowerCase()); //hello
    
            //3. concat拼接字符串
            String s1 = "宝玉";
            s1 = s1.concat("林黛玉").concat("together");
            System.out.println(s1); //宝玉林黛玉together
    
            //4. replace 替换字符串中的字符
            s1 = "宝玉 and 林黛玉 林黛玉 林黛玉";
            //在 s1 中,将 所有的 林黛玉 替换成薛宝钗
            // 老韩解读: s1.replace() 方法执行后,返回的结果才是替换过的.
            // 注意对 s1 没有任何影响
            String s2 = s1.replace("林黛玉", "xjz");
            System.out.println(s1); //宝玉 and 林黛玉 林黛玉 林黛玉
            System.out.println(s2); //宝玉 and xjz xjz xjz
    
            //5. split 分隔字符串,对于某些分割字符,我们需要 转义比如 | \\ 等
            String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";
            // 老师解读:
            // 1. 以 , 为标准对 poem 进行分割,返回一个数组
            // 2. 在对字符串进行分割时,如果有特殊字符,需要加入 转义符 \
            String[] split = poem.split(",");
            poem = "E:\\aaa\\bbb";
            split = poem.split("\\\\");
            System.out.println("===分割后内容===");
            for (int i = 0; i < split.length; i++) {
                System.out.println(split[i]);
            }
    
            //6. toCharArray 转换成字符数组
            s = "happy";
            char[] chs = s.toCharArray();
            for (int i = 0; i < chs.length; i++) {
                System.out.println(chs[i]);
            }
    
            //7. compareTo 比较两个字符串的大小,如果前者大,
            // 则返回正数,后者大,则返回负数,如果相等,返回 0
            // (1) 如果长度相同,并且每个字符也相同,就返回 0
            // (2) 如果长度相同或者不相同,但是在进行比较时,可以区分大小
            // 就返回 if (c1 != c2) {
            // return c1 - c2;
            // }
            // (3) 如果前面的部分都相同,就返回 str1.len - str2.len
            String a = "jac"; //len = 3
            String b = "jack"; //len = 4
            System.out.println(a.compareTo(b));//-1
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    2. StringBuffer 类

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

    2.1 String VS StringBuffer

    1) String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上是更改地址,效率极地 // private final char value[];

    2)StringBuffer 保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率极高 // char[] value; //这个放在堆

    2.2 String 和 StringBuffer 相互转换

    package com.xjz.stringbuffer;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class StringAndStringBuffer {
        public static void main(String[] args) {
    
            //看 String --》 StringBuffer
            String str = "hello tom";
            //方式1 使用构造器
            //注意:返回的才是 StringBuffer对象,对 str 本身没有影响
            StringBuffer stringBuffer = new StringBuffer(str);
    
            //方式2 使用的是 append 方法
            StringBuffer stringBuffer1 = new StringBuffer();
            stringBuffer1.append(str);
    
            //看看 StringBuffer -> String
            StringBuffer stringBuffer2 = new StringBuffer("xjz");
            //方式1 使用 StringBuffer 提供的 toString() 方法
            String s = stringBuffer2.toString();
            //方式2 使用构造器来搞定
            String s1 = new String(stringBuffer2);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.3 StringBuffer 类常见方法

    package com.xjz.stringbuffer;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class StringBufferMethod {
        public static void main(String[] args) {
    
            StringBuffer sb = new StringBuffer("hello");
            //增
            sb.append(","); //"hello,"
            sb.append("张三丰");//"hello,张三丰"
            sb.append("赵敏").append(100).append(true).append(10.5); //"hello,张三丰赵敏 100true10.5"
            System.out.println(sb);//"hello,张三丰赵敏 100true10.5"
    
            //删
            /*
             * 删除索引为>=start && 
            sb.delete(11,14);
            System.out.println(sb); //hello,张三丰赵敏true10.5
    
            //改
            // 使用 周芷若 替换 赵敏 即:索引 9-11 的字符 [9,11)
            sb.replace(9,11,"周芷若");
            System.out.println(sb); //hello,张三丰周芷若true10.5
    
            //查找指定的子串在字符串中第一次出现的索引,如果找不到索引返回 -1
            int indexOf = sb.indexOf("张三丰");
            System.out.println(indexOf); //6
    
            //插
            // 在索引为 9 的位置插入 “赵敏”,原来索引为 9 的内容自动后移
            sb.insert(9,"赵敏");
            System.out.println(sb); //hello,张三丰赵敏周芷若true10.5
    
            //长度 length
            System.out.println(sb.length());
            System.out.println(sb);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    3. StringBuilder 类

    1) 一个可变的字符序列,此类提供一个与 StringBuffer 兼容的 API,但不保证同步(StringBuilder 不是线程安全)。该类被设计用做 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的使用。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快

    2)在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接收任意类型的数据。

    3.1 StringBuilder 常用方法

    StringBuilder 和 StringBuffer 均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样。

    看一下源码

    image-20230912103711735

    package com.xjz.stringbuilder;
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class StringBuilder01 {
        public static void main(String[] args) {
            //1. StringBuilder 继承 AbstractStringBuilder 类
            //2. 实现了 Serializable ,说明 StringBuilder 对象是可以串行化(对象可以网络传输,可以保存到文件)
            //3. StringBuilder 是 final 类, 不能被继承
            //4. StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 char[] value;
            // 因此,字符序列是堆中
            //5. StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用
            // StringBuilder
            StringBuilder stringBuilder = new StringBuilder();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    4. String、StringBuffer 和 StringBuilder 的比较

    1)StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且方法也一样

    2)String:不可变字符序列,效率低,但是复用率高。

    3)StringBuffer:可变字符序列,效率较高(增删)、线程安全,看源码

    4)Stringbuilder:可变字符序列,效率最高,线程不安全

    5. String、StringBuffer 和 StringBuilder 的选择

    使用原则,结论如下:

    1. 如果字符串存在大量的修改操作,一般使用 StringBuffer 和 StringBuilder
    2. 如果字符串存在大量的修改操作,并在单线程情况下,使用StringBuilder
    3. 如果字符串存在大量的修改操作,并在多线程情况下,使用StringBuffer
    4. 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等

    StringBuilder 的方法和 StringBuffer 一样。

  • 相关阅读:
    【数据结构】二叉树的前中后序遍历
    Transformer系列目标检测模型小抄(1)
    C++信号量机制
    混合灰狼和布谷鸟搜索优化算法(Matlab完整代码实现)
    2022年最新辽宁建筑八大员(标准员)考试试题及答案
    Redbook Chapter 7: Query Optimization翻译批注
    Linux查找运行的Python脚本路径
    推特群推掀开营销新篇章
    代理正向 反向代理
    STM32F4串口USART发送为00的解决方案
  • 原文地址:https://blog.csdn.net/m0_53125903/article/details/132826203