七、java中的字符串(String、StringBuilder、StringJoiner)

发布时间:2024年01月10日

具体信息请查看 API 帮助文档

七、字符串

1.String类

? String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。Java 程序中所有的双引号字符串,都是 String 类的对象。

String 类在 java.lang 包下,所以使用的时候不需要导包!

1.1 特点

  1. 不可变性:String对象在创建后不可被修改。

     这意味着一旦一个String对象被赋值,它的值就不能再被改变。
    
     如果我们对一个String对象执行任何的修改操作,实际上是创建了一个全新的String对象来存储修改后的值。
    
     这样的设计是为了提高性能和安全性,因为不可变的String对象可以在多线程环境下共享而不会出现意外的修改。
    
  2. 字符串字面量:Java提供了字符串字面量的方式来表示String对象。

     字符串字面量是用双引号括起来的字符序列,例如:"Hello"。
    
     字符串字面量在编译时就会自动优化为String对象,可以直接使用,而不需要显式的调用构造函数。
    
     此外,多个字符串字面量可以通过"+"运算符连接起来,形成一个新的String对象。
    
  3. 字符编码:String类使用UTF-16编码(Unicode字符集的一种)来表示字符串,每个字符占用16位。

     我们可以通过`getBytes()`方法将字符串转换为指定的字符编码(如UTF-8)
    
  4. 字符串池:为了提高性能和节省内存,Java使用了字符串池的概念。

     字符串池是一个字符串缓存区域,存储着已经创建的字符串对象。
    
     当我们创建新的字符串对象时,首先会检查字符串池中是否已存在相同内容的字符串。
    
     如果存在,则返回池中的引用,而不会创建新的对象。
    
     这样可以减少内存消耗和垃圾回收的开销,提高程序的性能。
    
  5. 运算符重载:String类重载了加号"+"运算符,可以用于连接多个字符串。

     这个特性使得字符串拼接变得简洁和直观,例如:"Hello" + "World"将会得到一个新的字符串"HelloWorld"。
    
  6. 性能优化:由于String对象的不可变性,它们在多线程环境下是安全的并且可以被共享。

     这样可以避免许多并发问题,并提高程序的性能。
    
  7. 字符串拼接性能优化:在需要频繁拼接字符串的场景下,使用StringBuilder类或StringBuffer类可以提升性能。

     `StringBuilder`和`StringBuffer`是可变的字符序列,可以在原地修改字符串,而不需要创建新的对象。	
     
     `StringBuilder`是线程不安全的,适用于单线程环境。
    
     StringBuffer`是线程安全的,适用于多线程环境。
    

1.2 构造方法

  • 常用的构造方法
方法名说明
public String()创建一个空白字符串对象,不含有任何内容
public String(char[] chs)根据字符数组的内容,来创建字符串对象
public String(byte[] bys)根据字节数组的内容,来创建字符串对象
String s = “abc”;直接赋值的方式创建字符串对象,内容就是abc
  • 示例代码
public class StringDemo01 {
    public static void main(String[] args) {
        //public String():创建一个空白字符串对象,不含有任何内容
        String s1 = new String();
        System.out.println("s1:" + s1);

        //public String(char[] chs):根据字符数组的内容,来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println("s2:" + s2);

        //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        byte[] bys = {97, 98, 99};
        String s3 = new String(bys);
        System.out.println("s3:" + s3);

        //String s = “abc”;	直接赋值的方式创建字符串对象,内容就是abc
        String s4 = "abc";
        System.out.println("s4:" + s4);
    }
}

1.3 成员方法

方法名称描述
char charAt(int index)返回指定索引处的 char 值。
int compareTo(String anotherString)按字典顺序比较两个字符串。
int compareToIgnoreCase(String str)按字典顺序比较两个字符串,不考虑大小写。
boolean equals(Object anObject)将此字符串与指定的对象比较。
boolean equalsIgnoreCase(String anotherString)将此 String 与另一个 String 比较,不考虑大小写。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此字符串复制到目标字符数组。
int length()返回此字符串的长度。
String replace(char oldChar, char newChar)返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串。
String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串。
String toString()返回此对象本身(它已经是一个字符串!)。

这些方法均属于String类中的实例方法,用于操作字符串。具体来说:

- `charAt(int index)`方法用于获取指定索引位置上的字符。

- `compareTo(String anotherString)`方法用于比较两个字符串,按字典顺序比较。

- `compareToIgnoreCase(String str)`方法与`compareTo`方法类似,但不考虑大小写。

- `equals(Object anObject)`方法用于判断当前字符串是否与指定的对象相等。

- `equalsIgnoreCase(String anotherString)`方法与`equals`方法类似,但不考虑大小写。

- `getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)`方法用于将当前字符串中指定范围的字符复制到目标字符数组中。

- `length()`方法用于获取当前字符串的长度。

- `replace(char oldChar, char newChar)`方法用于替换当前字符串中指定字符的值。

- `substring(int beginIndex)`方法用于获取当前字符串中子串,从指定索引位置开始到结尾。

- `substring(int beginIndex, int endIndex)`方法用于获取当前字符串中子串,从指定开始索引位置到指定结束索引位置的子串。

- `toString()`方法用于将当前对象转换为字符串,该方法的实现返回当前对象本身,因为`String`本身就是一个字符串。

1.4 创建对象方式的区别

  • 通过构造方法创建

    ? 通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同

  • 直接赋值方式创建

    ? 以“ ”方式给出的字符串,只要字符串相同,JVM 都只会建立一个 String 对象,并在字符串池中维护

1.5 字符串的比较

1.5.1 ==号的作用
  • 比较基本数据类型:比较的是具体的值
  • 比较引用数据类型:比较的是对象地址值
1.5.2 equals方法
  • 方法介绍

    public boolean equals(String s)     比较两个字符串内容是否相同、区分大小写
    

    示例代码:

    public class StringDemo02 {
        public static void main(String[] args) {
            //构造方法的方式得到对象
            char[] chs = {'a', 'b', 'c'};
            String s1 = new String(chs);
            String s2 = new String(chs);
    
            //直接赋值的方式得到对象
            String s3 = "abc";
            String s4 = "abc";
    
            //比较字符串对象地址是否相同
            System.out.println(s1 == s2);//false
            System.out.println(s1 == s3);//false
            System.out.println(s3 == s4);//true
            System.out.println("--------");
    
            //比较字符串内容是否相同
            System.out.println(s1.equals(s2));//true
            System.out.println(s1.equals(s3));//true
            System.out.println(s3.equals(s4));//true
        }
    }
    

2. StringBuilder

2.1 构造方法

  • 空参构造
StringBuilder stringBuilder=new StringBuilder();
  • 带参构造
StringBuilder stringBuilder=new StringBuilder("aaaa");

2.2 成员方法

  • append() :添加StringBuilder的内容

  • reverse() :反转StringBuilder的内容

  • length() :获取StringBuilder的长度

  • toString(): 转换成字符串

      (因为StringBuilder是一个长度可变容器,需要将最后结果转换成字符串,字符串长度固定,不可变)
    

注意:StringBuilder打印的不是地址值而是属性值,因为其是java已经写好的类,在底层对其进行了一些处理

	StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。

例如:

public class StringBuilderDemo3 {
    public static void main(String[] args) {
        //1.创建对象
        StringBuilder sb = new StringBuilder("abc");

        //2.添加元素
        /*sb.append(1);
        sb.append(2.3);
        sb.append(true);*/

        //反转
        sb.reverse();

        //获取长度
        int len = sb.length();
        System.out.println(len);

        System.out.println(sb);
    }
}

3. StringJoiner

3.1 构造方法

  • StringJoiner stringJoiner=new StringJoiner(“delimiter”);

    delimiter:间隔符号
    
  • StringJoiner stringJoiner=new StringJoiner(“delimiter”,“prefix”,“suffix”); 、

    delimiter:间隔符号;prefix:开始符号;suffix:结束符号;
    

3.2 成员方法

  • add() 添加StringJoiner的内容

  • length() 获取StringJoiner的长度

       注意:长度为所有的字符的长度,包括间隔符号,开始符号,结束符号
    
  • toString() 转换成字符串

      (因为StringJoiner是一个长度可变容器,需要将最后结果转换成字符串,串长度固定,不可变)
    

注意:StringJoiner打印的不是地址值而是属性值,因为其是java已经写好的类,在底层对其进行了一些处理

例如:

//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);//aaa---bbb---ccc
//1.创建对象
StringJoiner sj = new StringJoiner(", ","[","]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//15
//3.打印
System.out.println(sj);//[aaa, bbb, ccc]
String str = sj.toString();
System.out.println(str);//[aaa, bbb, ccc]

4. 字符串原理

  1. 字符串存储的内存原理

    • 直接赋值会复用字符串串池中的
    • new出来的不会复用,而是开辟一个新的空间
  2. ==号比较的到底是什么?

    如果比较的是基本数据类型:比的是具体的数值是否相等。

    如果比较的是引用数据类型:比的是地址值是否相等。

  3. 字符串拼接的底层原理

    • 字符串拼接包含变量:

      当字符串拼接包含变量时,使用+运算符进行拼接,底层会使用StringBuilder类来执行拼接操作。

      StringBuilder类在拼接变量时,会将变量的值转换为字符串并追加到当前的StringBuilder对象中。

      例如:

      String name = "Alice";
      int age = 25;
      String message = "My name is " + name + " and I am " + age + " years old.";
      

      这段代码编译后的实际执行是:

      StringBuilder sb = new StringBuilder();
      sb.append("My name is ");
      sb.append(name);
      sb.append(" and I am ");
      sb.append(age);
      sb.append(" years old.");
      String message = sb.toString();
      

      可以看到,变量名和值都被转换为字符串,并追加到StringBuilder对象中,然后通过toString()方法得到最终的拼接结果。

    • 字符串拼接不包含变量:

      当字符串拼接不包含变量时,使用+运算符进行拼接,底层会直接进行字符串的连接操作。

      由于没有变量,编译器可以在编译时确定整个拼接结果。

      例如:

      String str1 = "Hello";
      String str2 = "World";
      String result = str1 + ", " + str2;
      

      这段代码编译后的实际执行是:

      String result = "Hello, " + "World";
      

      可以看到,编译器直接将不同字符串字面量连接在一起,形成最终的拼接结果。

  4. StringBuilder提高效率原理

    • 可变性:StringBuilder是可变的字符序列,可以在原地修改字符串内容。相比于String类的不可变性,使用StringBuilder可以避免频繁创建新的字符串对象。

    • 内部缓冲区:StringBuilder内部使用一个可扩展的字符数组作为缓冲区,用于存储字符串的内容。在进行字符串拼接时,StringBuilder会将新的字符追加到缓冲区中。

    • 避免创建中间对象:当使用+运算符或concat()方法进行字符串拼接时,每次拼接都会创建一个新的字符串对象。而StringBuilder则避免了这一点,在进行拼接操作时直接在缓冲区中修改字符串内容,避免了频繁创建新的字符串对象。

       需要注意的是,`StringBuilder`是非线程安全的。
      
       如果在多线程环境下进行字符串操作,应该使用线程安全的`StringBuffer`类来替代`StringBuilder`。		
      
       `StringBuffer`的使用方式和`StringBuilder`类似,但具备线程安全的特性。
      

具体信息请查看 API 帮助文档

文章来源:https://blog.csdn.net/kuxiaoyang/article/details/135483282
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。