JavaSE 第八章 Java常用类 之 String&StringBuffer&StringBuilder

活动地址:CSDN21天学习挑战赛

9.1 字符串相关类

9.1.1 String的特性

  • String类:代表字符串。Java程序中所有的字符串字面值都作为该类的实例实现
  • String是一个final类,代表不可它不可被继承
    *
    字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
  • String对象的字符内容是存储在一个字符数组value[]中的。(从JDK9开始,String类的底层就改用byte类型的数组进行实现了)

9.1.2 String类的特点:

  • 字符串对象是Java中唯一一个不需要new关键字就可以创建的对象 String s = "abc";

    • 对于数组,数组:int[] arr = {1 , 2 , 3};这种只是省略了new关键字,他还是存在的
    • 包装类:Integer a = 5 ; 这种是Integer a = Integer.valusOf(5);的简化写法,属于自动装箱
  • 字符串对象是Java中唯一一个既是对象又是常量的类型

    • 字面值常量包括:整数型、小数型、字符型、布尔型、空常量null、字符串型
  • 字符串对象是Java中唯一一个可以做加法运算的对象(字符串拼接操作

    • 对于包装类类型之间的加法操作是自动拆箱后进行的
  • 字符串不能改变

  • 字符串是共享的

    • String str1 = "abc"; String str2 = "abc"; 在内存中只存在一个"abc"字符串
  • 字符串的本质是一个char数组(1.8之前)

    • JDK9之后,字符串就改为了byte数组存储
  • JDK8的String类

在这里插入图片描述

  • JDK17的String类
    在这里插入图片描述

从上面的源码中可以看到,无论是char数组还是byte数组都是被final修饰的,表示字符串是一个不可变的序列

示例:定义字符串常量,并画出其在内存中的存储位置

String s1 = "abc" ;
String s2 = "abc" ;
System.out.println(s1 == s2);   // true
s1 = "hello" ;
System.out.println(s1 == s2);   // false
  • JDK1.7之前的字符串常量池是在方法区中的(在后续JDK的版本变化中,常量池的位置有所改变)

我们可以从图中很清楚的看出,s1的原本的字符串值并没有发生改变,发生改变的是其地址值,它的指向发生了改变,String是一个不可变的字符序列
在这里插入图片描述

9.1.3 字符串的两种创建方式

String的两种创建方式:

  • 直接赋值:字符串常量

  • 通过new关键字创建:创建的是字符串对象(非常量对象)

String str1 = "abc";
String str2 = new String("abc");

两者之间的区别:

  • 字符串常量存储在字符串常量池中,目的是共享

  • 字符串非常量对象存储在堆中

示例:

public class Demo1 {
    public static void main(String[] args) {
        String s1 = "abc" ;
        String s2 = "abc" ;
        String s3 = new String("abc") ;

        System.out.println(s1 == s2);	// true
        System.out.println(s1 == s3);	// false

    }
}

在这里插入图片描述

9.1.4 字符串之间的拼接

示例:

public class Demo2 {
    public static void main(String[] args) {
        String s1 = "Hello" ;
        String s2 = "World" ;
        String s3 = "Hello" + "World" ;
        String s4 = s1 + "World" ;
        String s5 = s1 + s2 ;
        String s6 = (s1 + s2).intern() ;
        String s7 = "HelloWorld" ;

        System.out.println(s3 == s4);   // false
        System.out.println(s3 == s5);   // false
        System.out.println(s3 == s6);   // true
        System.out.println(s3 == s7);   // true
        System.out.println(s4 == s5);   // false
    }
}

在这里插入图片描述
结论:

  • 常量与常量拼接的结果在常量池中,且常量池中不会存在内容相同的常量
  • 常量与变量或变量与变量的拼接结果在堆中
  • 如果拼接的结果调用intern()方法,返回值就在常量池中
  • String s1 = "a";

    • 说明:在字符串常量池中创建了一个字面量为"a"的字符串。
  • s1 = s1 + "b";

    • 说明:实际上原来的“a”字符串对象已经丢弃了,现在在堆空间中产生了一个字符
      串s1+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本
      字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响 程序的性能。
  • String s2 = "ab";

    • 说明:直接在字符串常量池中创建一个字面量为"ab"的字符串。
  • String s3 = "a" + "b";

    • 说明:s3指向字符串常量池中已经创建的"ab"的字符串。
  • String s4 = s1.intern();

    • 说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的"ab"字符串 赋值给s4。

9.1.5 String作为实参

public class Demo3 {
    public static void main(String[] args) {
        String str = new String("abcd") ;
        char[] chars = {'a' , 'b' , 'c' , 'd'} ;

        change(str , chars);

        System.out.println(str);    // abcd
        for (int i = 0; i < chars.length; i++) {    // a  w  c  d
            System.out.print(chars[i] + "\t");
        }
    }

    public static void change(String str , char ch[]) {
        str = "test" ;
        ch[1] = 'w' ;
    }
}

在这里插入图片描述

9.1.6 String类的API

9.1.6.1 字符串的比较功能

boolean equals(Object anObject):比较调用方法字符串对象和传入的对象内容是否相等(可用于账号密码的校验)

boolean equalsIgnoreCase(String anotherString):比较调用方法字符串对象和传入的字符串对象内容是否相等,忽略大小写

案例:模拟登录功能

import java.util.Scanner;

public class Demo1 {
    public static void main(String[] args) {
        login();    // 调用方法
    }

    public static void login() {
        // 定义用户名、密码和验证码
        String username = "zhangsan" ;
        String password = "123456" ;
        String checkWord = "FH8l" ;

        // 对于账号和密码的验证,必须要求完全相等,使用equals()方法作比较
        // 对于验证码的验证,可以忽略大小写,使用equalsIgnoreCase()方法作比较

        Scanner sc = new Scanner(System.in) ;

        for (int i = 3 ; i > 0 ; i --) {
            System.out.print("请示输入用户名:");
            String uname = sc.nextLine();

            System.out.print("请输入密码:");
            String pwd = sc.nextLine();

            System.out.print("请输入验证码(" + checkWord + "):");
            String cw = sc.nextLine();

            // 账号、密码、验证码都正确
            if (username.equals(uname) && password.equals(pwd) && checkWord.equalsIgnoreCase(cw)) {
                System.out.println("登陆成功");
//                return;
                break;  // 退出循环,结束程序
            } else {
                if (i > 1) {
                    System.out.println("您的用户名密码或验证码有误,请重新输入!(您还有" + (i - 1) + ")次登录机会");
                } else {
                    System.out.println("账号锁定");
                }
            }
        }
        sc.close(); // 关闭资源

    }
}

三次都输入错误:

在这里插入图片描述
登陆成功:
在这里插入图片描述

String类中equals方法的源码:
	@Override
	public boolean equals(Object anObject) {
        //第一层 : 判断 调用方法的对象 == 传入方法的对象
        if (this == anObject) { //判断调用者和传入方法的对象是否为同一个对象,提高效率
            //能进来说明两个对象是同一个对象,直接返回true
            return true;
        }
        
        //第二层 : 判断 传入的对象是否是 String 类型
        if (anObject instanceof String) { //使用instanceof关键字判断传入参数是否为String类型,如果是String类型,则在下面代码中可以安全的进行向下转型;如果不是String类型,直接返回false。提高了代码的安全性
            
            String anotherString = (String)anObject; //把传入的对象向下转型成String对象

            //value : 是String类中的成员变量 -> char[] value 
            int n = /*this.*/value.length;//获取调用方法的字符串对象的长度(也就是字符个数)
            
            //判断 : 调用方法的字符串对象的长度 是否和 传入方法字符串对象的长度一致 
            if (n == anotherString.value.length) {
                
                //能进来说明2个字符串对象的长度一致的
                
                char v1[] = /*this.*/value; //获取调用方法的字符串对象的底层字符数组
                char v2[] = anotherString.value;//获取传入方法字符串对象的底层字符数组
                
                int i = 0; //初始化语句
                while (n-- != 0) {//n-- != 0 : 通过字符串的字符个数控制循环的次数
                    
                    //判断 : 调用方法字符串的某个索引位置的字符 不等于 传入方法字符串对象的同索引字符
                    if (v1[i] != v2[i]){ //'a' != 'b' -> true
                        //只要有一个索引位置的字符不相同,equals方法的结果就是false -> 两个字符串不相同
                        return false;
                    }
                    //控制索引
                    i++;
                }
                //能从上方的循环下来,说明两个个字符串的每一个索引位置字符都相同 -> 两个字符串内容相同
                return true;
            }
        }
        return false;
    }
9.1.6.2 字符串转换功能

char[] toCharArray() : 把字符串对象转换成字符数组

byte[] getBytes() : 把字符串对象转换成字节数组(按照平台默认编码格式)
byte[] getBytes(String charsetName) : 把字符串对象转换成字节数组(按照指定编码格式)

汉字字节都是以负数开头

UTF-8 : 互联网统一编码表 -> 一个中文占用3个字节
GBK : 中国的编码表 ->一个中文占用2个字节

示例:

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Demo2 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        /*
            char[] toCharArray() : 把字符串对象转换成字符数组,返回一个char型数组
            byte[] getBytes() : 把字符串对象转换成字节数组,返回个byte数组(按照平台默认编码格式)
            byte[] getBytes(String charsetName) : 把字符串对象转换成字节数组,返回个byte数组(按照指定编码格式)
        */

        String str = "HelloWorld" ;

        char[] charArray = str.toCharArray();
        byte[] bytes1 = str.getBytes();
        byte[] bytes2 = str.getBytes("utf-8");  // 因为getBytes(String charsetName)方法抛出的有异常,所以我们在调用它时要对异常进行处理

        System.out.println("charArray = " + Arrays.toString(charArray));
        System.out.println("bytes1 = " + Arrays.toString(bytes1));
        System.out.println("bytes2 = " + Arrays.toString(bytes2));

        String str1 = "我爱爪洼" ;
        byte[] bytes3 = str1.getBytes();
        byte[] bytes4 = str1.getBytes("GBK");
        System.out.println("bytes3 = " + Arrays.toString(bytes3));
        System.out.println("bytes4 = " + Arrays.toString(bytes4));

    }
}

在这里插入图片描述

String toUpperCase() : 把字符串中所有的英文小写字符变成大写字符
String toLowerCase() : 把字符串中所有的英文大写字符变成小写字符

示例:

public class Demo3 {
    public static void main(String[] args) {
        /*
            String toUpperCase()  : 把字符串中所有的英文小写字符变成大写字符
            String toLowerCase() :  把字符串中所有的英文大写字符变成小写字符 
         */

        String str = "HelloWorld" ;

        String upperCase = str.toUpperCase();
        String lowerCase = str.toLowerCase();

        System.out.println("upperCase = " + upperCase);
        System.out.println("lowerCase = " + lowerCase);
    }
}
9.1.6.3 字符串的获取功能

//字符串的遍历
char charAt(int index) :

  • 获取指定索引位置上的元素

int length():

  • 获取字符串的长度/字符的个数

//如果不存在都返回 -1

int indexOf(int ch) :

  • 获取传入的字符第一次出现在原字符串的索引位置

int indexOf(int ch, int fromIndex) :

  • 获取传入的字符第一次出现在原字符串的索引位置。fromIndex :从哪个索引位置开始算第一次出现

int indexOf(String str) :
int indexOf(String str, int fromIndex)

  • 获取传入的字符串第一次出现在原字符串的索引位置

//如果不存在都返回 -1
int lastIndexOf(int ch) :

  • 获取传入的字符最后一次出现在原字符串的索引位置

int lastIndexOf(int ch, int fromIndex) :

  • 获取传入的字符最后一次出现在原字符串的索引位置。fromIndex : 从哪个索引位置开始算第一次出现 int

lastIndexOf(String str) :
lastIndexOf(String str, int fromIndex)

  • 获取传入的字符串最后一次出现在原字符串的索引位置 int

示例:

public class Demo4 {
    public static void main(String[] args) {

        String str = "HelloWorld" ;

            //字符串的遍历
//        char charAt(int index) : 获取指定索引位置上的元素
        char c = str.charAt(5);
        System.out.println("c = " + c);
        System.out.println("------------------");

//        int length(): 获取字符串的长度/字符的个数 //如果不存在都返回 -1
        int length = str.length();
        System.out.println("length = " + length);
        for (int i = 0 ; i < str.length() ; i ++) {
            System.out.print(str.charAt(i) + ",");
        }
        System.out.println();
        System.out.println("------------------");

//        int indexOf(int ch) : 获取传入的字符第一次出现在原字符串的索引位置  如果不存在都返回 -1
        int l = str.indexOf('l');
        int n = str.indexOf('n');
        System.out.println("l = " + l);
        System.out.println("n = " + n);
        System.out.println("------------------");

//        int indexOf(int ch, int fromIndex) :获取传入的字符第一次出现在原字符串的索引位置。fromIndex : 从哪个索引位置开始算第一次出现
        int l1 = str.indexOf('l', 5);
        int n1 = str.indexOf('n', 5);
        System.out.println("l1 = " + l1);
        System.out.println("n1 = " + n1);
        System.out.println("------------------");

//        int indexOf(String str) : 获取传入的字符串第一次出现在原字符串的索引位置
//        int indexOf(String str, int fromIndex) //如果不存在都返回 -1
        int llo = str.indexOf("llo");
        int abc = str.indexOf("abc");
        System.out.println("llo = " + llo);
        System.out.println("abc = " + abc);

        int llo1 = str.indexOf("llo", 3);
        System.out.println("llo1 = " + llo1);
        System.out.println("------------------");

//        int lastIndexOf(int ch) : 获取传入的字符最后一次出现在原字符串的索引位置
//        int lastIndexOf(int ch, int fromIndex) :获取传入的字符最后一次出现在原字符串的索引位置。fromIndex : 从哪个索引位置开始算第一次出现
        int l2 = str.lastIndexOf('l');
        int l3 = str.lastIndexOf('l', 7);
        System.out.println("l2 = " + l2);
        System.out.println("l3 = " + l3);
        System.out.println("------------------");


//        int lastIndexOf(String str) : 获取传入的字符串最后一次出现在原字符串的索引位置
//        int lastIndexOf(String str, int fromIndex)
        int llo2 = str.lastIndexOf("llo");
        int abc1 = str.lastIndexOf("abc", 8);
        System.out.println("llo2 = " + llo2);
        System.out.println("abc1 = " + abc1);
    }
}

在这里插入图片描述

9.1.6.4 字符串的判断功能

boolean contains(CharSequence s) :

  • 判断传入的字符串是否包含于源字符串中

boolean startsWith(String prefix) :

  • 判断调用方法的字符串对象是否以prefix开头 可以用于判断姓氏

boolean endsWith(String suffix) :

  • 判断调用方法的字符串对象是否以suffix结尾 可以用于判断文件后缀名

boolean isEmpty() :

  • 判断调用方法的字符串对象是否是空字符串 -> ""

示例:

public class Demo5 {
    public static void main(String[] args) {

        String str = "HelloWorld" ;

//        boolean contains(CharSequence s) : 判断传入的字符串是否包含于源字符串中
        boolean world = str.contains("World");
        System.out.println("world = " + world);

//        boolean startsWith(String prefix) : 判断调用方法的字符串对象是否以prefix开头 可以用于判断姓氏
        boolean b = str.startsWith("He");
        System.out.println("b = " + b);

//        boolean endsWith(String suffix) : 判断调用方法的字符串对象是否以suffix结尾 可以用于判断文件后缀名
        boolean b1 = str.endsWith("rld");
        System.out.println("b1 = " + b1);

//        boolean isEmpty() : 判断调用方法的字符串对象是否是空字符串 -> ""
        boolean b2 = str.isEmpty();
        System.out.println("b2 = " + b2);
9.1.6.5 字符串的截取功能

String substring(int beginIndex) :

  • 从beginIndex索引开始截取原字符串到末尾,生成新的字符串对象

String substring(int beginIndex, int endIndex) :

  • 从beginIndex索引开始截取原字符串到endIndex索引,生成新的字符串对象 -> [beginIndex,endIndex - 1]

示例:

public class Demo6 {
    public static void main(String[] args) {
        String str = "HelloWorld" ;
//        String substring(int beginIndex) : 从beginIndex索引开始截取原字符串到末尾,生成新的字符串对象
        String substring = str.substring(3);
        System.out.println("substring = " + substring); // substring = loWorld

//        String substring(int beginIndex, int endIndex) :从beginIndex索引开始截取原字符串到endIndex索引,生成新的字符串对象  [beginIndex,endIndex - 1]
        String substring1 = str.substring(3, 8);
        System.out.println("substring1 = " + substring1); // substring1 = loWor

    }
}
9.1.6.6 字符串的替换功能

//敏感字屏蔽
String replace(char oldChar, char newChar) :

  • 把源字符串中oldChar全部替换成newChar字符,并生成新的字符串对象 String replace(CharSequence

target, CharSequence replacement) :

  • 把源字符串中target字符串全部替换成replacement字符串,并生成新的字符串对象

示例:

public class Demo7 {
    public static void main(String[] args) {
        //敏感字屏蔽
        // String replace(char oldChar, char newChar) : 把源字符串中oldChar全部替换成newChar字符,并生成新的字符串对象
        String str = "你是小学生吧?" ;
        String s = str.replace('小', '大');
        System.out.println("s = " + s);     // s = 你是大学生吧?

        // String replace(CharSequence target, CharSequence replacement) : 把源字符串中target字符串全部替换成replacement字符串,并生成新的字符串对象
        String s1 = str.replace("小学生", "***");
        System.out.println("s1 = " + s1);   // s1 = 你是***吧?
    }
}
9.1.6.7 字符串的切割功能

String[] split(String regex) : 按照传入的字符串切割原字符串,得到切割后的字符串数组

第一层 : 按什么切就传入什么字符串

第二层 : regex -> 正则表达式
x : 传什么就是什么
x+ : x出现1次或者多次都按一次算
. : 正则的通配符 可以代表任意字符
转义符 : \ -> 把\后面的内容转义成原本的含义或其他的含义

示例:

import java.util.Arrays;

public class Demo8 {
    public static void main(String[] args) {
        /*
            String[] split(String regex) : 按照传入的字符串切割原字符串,得到切割后的字符串数组

            第一层 : 按什么切就传入什么字符串
            第二层 : regex -> 正则表达式
        */

        String str1 = "a,b,c,d,e,f,g" ;
        String str2 = "a b c d e f g" ;
        String[] split = str1.split(",");
        String[] split1 = str2.split(" ");
        System.out.println("split = " + Arrays.toString(split));
        System.out.println("split1 = " + Arrays.toString(split1));

        String str3 = "a    b     c                    d    e  f  g" ;
        String[] split2 = str3.split(" +");  // 正则表达式 x+    x代表任意字符,x+表示任意多个x字符
        System.out.println("split2 = " + Arrays.toString(split2));

    }
}

在这里插入图片描述

9.1.6.8 字符串的匹配功能

boolean matches(String regex) : 校验字符串对象内容是否符合正则规则

示例:验证手机号

public class Demo9 {
    public static void main(String[] args) {
        // boolean matches(String regex) : 校验字符串对象内容是否符合正则规则
        String str = "13701234567" ;
        String str1 = "137012345670" ;

        boolean matches = str.matches("^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$");
        boolean matches1 = str1.matches("^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$");
        System.out.println("matches = " + matches);     // true
        System.out.println("matches1 = " + matches1);   // false
    }
}
9.1.6.9 字符串的其他功能

String concat(String str) : 把传入的字符串对象连接到调用方法的字符串对象上,并生成新的字符串对象

String toString() : 把字符串对象转换成字符串对象

String trim(): 去除字符串对象2端的空格,并生成新的字符串
static String valueOf(任意类型的对象) : 把传入的对象转换成String类型

示例:

public class Demo10 {
    public static void main(String[] args) {
//        String concat(String str) : 把传入的字符串对象连接到调用方法的字符串对象上,并生成新的字符串对象
        String str1 = "Hello" ;
        String str2 = "World" ;
        String concat = str1.concat(str2);
        System.out.println("concat = " + concat);   // 此方法用的不多,+ 拼接符更好用

//        String toString() : 把字符串对象转换成字符串对象
        String str3 = "HelloWorld" ;
        String s = str3.toString(); // 这个方法没什么用...
        System.out.println("s = " + s);

//        String trim(): 去除字符串对象2端的空格,并生成新的字符串
        String str4 = "Hello    World" ;
        String str5 = "    Hello    World    " ;
        String trim = str4.trim();
        String trim1 = str5.trim();
        System.out.println("trim = " + trim);
        System.out.println("trim1 = " + trim1);

//        static String valueOf(任意类型) : 把传入的对象/基本数据类型的数值转换成String类型
        char[] c = {'a' , 'b' , 'c' , 'd'};
        String s1 = String.valueOf(c);
        String s2 = String.valueOf(12345);
        System.out.println("s1 = " + s1);
        System.out.println("s3 = " + s2);

    }
}

在这里插入图片描述

9.1.7 StringBuffer类

  • java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,它可以对字符串进行增删,且不会产生新的对象
  • StringBuffer的很多方法与String相同
  • StringBuffer作为参数传递时,方法内部可以改变值

StringBuffer的父类是AbstracStringBuffer

在这里插入图片描述
在这里插入图片描述

  • StringBuffer类不同于String类,其对象必须使用构造器进行创建

    • StringBuffer():创建一个初始容量为16的字符串缓冲区
    • StringBuffer(int capacity):创建一个指定容量的字符串缓冲区
    • StringBuffer(String str):将内容初始化为指定字符串内容,其容量大小为str.length + 16
9.7.1.1 StringBuffer和String最为参数传递时的不同:

示例:

public class Demo1 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("HelloWorld") ;
        String s = "HelloWorld" ;
        change(sb , s);
        System.out.println("sb = " + sb);
        System.out.println("s = " + s);

    }

    public static void change(StringBuffer sb , String s) {
        sb.append("123123") ;
        s += "123123" ;
    }
}

在这里插入图片描述
内存图分析:
在这里插入图片描述

9.1.7.2 StringBuffer类常用的方法
  • StringBuffer append(xxx) : 用于字符串的拼接。append()方法的参数可以是任意类型,包括基本数据类型和引用数据类型

  • StringBuffer delete(int start, int end):删除指定位置的内容,start是开始索引,end是结束索引。[sart , end)

  • StringBuffer replace(int start, int end, String str) : 字符串的替换,将[start, end)位置的字符串替换为str

  • StringBuffer reverse() : 字符串反转

  • StringBuffer insert(int offset, String str) : 在指定索引处插入字符串str

示例:

public class Demo2 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("HelloWorld") ;

        // 在原字符串后面加上"HelloJava"
        sb.append("HelloJava") ;
        System.out.println("sb = " + sb);   // HelloWorldHelloJava

        // 删除索引[8,13)处的字符串
        sb.delete(8 , 13) ;
        System.out.println("sb = " + sb);   // HelloWorloJava

        // 替换索引[2,5)处的字符串为  aaaaa
        sb.replace(2 , 5 , "aaa") ;
        System.out.println("sb = " + sb);   // HeaaaWorloJava

        // 字符串反转
        sb.reverse() ;
        System.out.println("sb = " + sb);   // avaJolroWaaaeH

        // 在索引2处插入字符串  bbbb
        sb.insert(2 , "bbbb") ;
        System.out.println("sb = " + sb);   //avbbbbaJolroWaaaeH
    }
}
  • 当使用append()方法和insert()方法时,如果容器的大小不够会自动进行扩容
  • 上述方法都支持方法链操作
sb.append("123").insert(2 , "aaa").reverse() ;

之所以支持方法链,是因为每次调用方法后返回的都是调用者本身

在这里插入图片描述
StringBuffer中也定义有String类中的方法

char charAt(int index)
void setCharAt(int index, char ch)
int indexOf(String str)
int indexOf(String str, int fromIndex)
int lastIndexOf(String str)
int lastIndexOf(String str, int fromIndex)
int length()
String substring(int start)
String substring(int start, int end)

9.1.8 StringBuilder类

  • StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且 提供相关功能的方法也一样

在这里插入图片描述

  • StringBuffer和StringBuilder的区别就是StringBuffer是线程安全的,方法上都带有synchronized关键字修饰,StringBuilder没有。

在这里插入图片描述

String、StringBuffer、StringBuilder三者对于字符串拼接的效率测试

public class Demo3 {
    public static void main(String[] args) {
        long startTime = 0L ;
        long endTime = 0L ;

        String str = "" ;
        StringBuffer sBuffer = new StringBuffer("") ;
        StringBuilder sBuilder = new StringBuilder("") ;

        startTime = System.currentTimeMillis() ;
        for (int i = 0 ; i < 20000 ; i ++) {
            str += i ;
        }
        endTime = System.currentTimeMillis() ;
        System.out.println("String效率:" + (endTime - startTime));

        startTime = System.currentTimeMillis() ;
        for (int i = 0 ; i < 20000 ; i ++) {
            sBuffer.append(i) ;
        }
        endTime = System.currentTimeMillis() ;
        System.out.println("StringBuffer效率:" + (endTime - startTime));

        startTime = System.currentTimeMillis() ;
        for (int i = 0 ; i < 20000 ; i ++) {
            sBuilder.append(i) ;
        }
        endTime = System.currentTimeMillis() ;
        System.out.println("StringBuilder效率:" + (endTime - startTime));

    }
}

在这里插入图片描述
String的效率最低,StringBuffer次之,StringBuilder效率最高

String、StringBuffer、StringBuilder三者的异同

  • 在JDK8之前,String(JDK1.0),StringBuffer(JDK1.0)、StringBuilder(JDK5.0)三者底层都是使用char字符数组实现的,而在JDK8之后String底层改为byte数组。

  • String对象被final修饰,是一个不可改变的字符序列,而StringBuffer和StringBuilder是可改变的字符序列

  • String创建对象时可以不使用new关键字,且此时创建的字符串在常量池中存储

  • 因为String字符串是不可变序列,每次拼接都需要创建额外的String对象,StringBuffer和StringBuilder则不会

  • StringBuffer底层使用synchronized关键字修饰,为线程安全的,StringBuilder没有synchronized关键字修饰,为线程不安全的,所以StringBuffer的效率要低于StringBuilder

  • 三者在对字符串进行拼接时,StingBuilder效率最高,Sting效率最低

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值