Java常用類之字符串相關類使用詳解

字符串相關類

String、StringBuilder、StringBuffer類是三個字符串相關類。

String類代表不可變字符序列,StringBuilder類和StringBuffer類代表可變字符序列。

關於這三個類的詳細的用法,在筆試和面試以及實際開發中經常能用到,我們必須掌握好它。

1.String類的使用

String的常用方法:

1.isEmpty()如果字符串為空返回 true,否則返回 false

2.length()計算字符串長度

3.isBlank()如果給定的字符串為空或僅包含空格代碼點,則此方法返回 true ,否則返回 false

4.startsWith()是否以括號內的字符串開始

5.endsWith()是否以括號內的字符串結束

6.toLowerCase()生成一個新的字符串,字符串的英文字符全部變小寫

7.toUpperCase()生成一個新的字符串,字符串的英文字符全部變大寫

8.charAt()返回指定索引位置的char值。索引范圍為0~length()-1

9.substring(int startIndex)子字符串從索引開始

10.substring(int startIndex,int endIndex)返回一個字符串,該字符串是此字符串的子字符串。

子串開始於指定beginIndex並延伸到字符索引endIndex- 1

11.public int indexOf(int ch) 返回指定字符第一次出現的字符串內的第一個索引

12.indexOf(String str, int fromIndex)返回指定子串的第一次出現的字符串中的索引,從指定的索引開始

13.lastIndexOf 從後向前查詢第一次遇到的指定字符串的索引位置,註意索引還是從前往後數起

14.split()方法:分割字符串,參數regex稱為分割符,可以使用正則表達式來表示

15.replace()用於在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串。區分大小寫

16.replaceAll(String regex,String replacement)用給定的替換替換與給定的regular expression匹配的此字符串的每個子字符串。regex – 要匹配此字符串的正則表達式, replacement – 要替換每個匹配的字

17.trim()去掉字符串兩邊的空格

18.toCharArray()將字符串轉換為字符數組

19.concat()方法,在字符串的末尾追加子串

20.contains()當且僅當此字符串包含指定的char值序列時,返回true

21.compareTo()返回比較的前後兩個字符串的ASCII碼的差值,如果兩個字符串首字母不同,則該方法返回首字母的ASCII碼的差值,如果首字符相同,則比較下一個字符,直到有不同的為止,返回該不同的字符的ASCII碼差值。如果兩個字符串不一樣長,可以參與比較的字符又完全一樣,則返回兩個字符串的長度差值。

例子1:

package li.normalclass.stringclass;
 
import java.util.Arrays;
 
public class TestString {
    public static void main(String[] args) {
        // 1.如何創建String對象
        String str = "北京天安門abc";
 
        // 2.如何使用String對象
        // 2.1最簡單的方法
        System.out.println(str.length() );//8  註意是字符的個數,不是字節的個數
 
        //如果字符串為空返回 true,否則返回 false
        System.out.println(str.isEmpty());//false
 
        //jdk11新增的方法,如果給定的字符串為空或僅包含空格代碼點,則此方法返回 true ,否則返回 false
        System.out.println(str.isBlank());//false
 
        //是否已括號內的字符串為開始
        System.out.println(str.startsWith("北京天"));//true
 
        // 是否已括號內的字符串為結束
        System.out.println(str.endsWith("c"));//true
 
         //生成一個新的字符串,字符串的英文字符全部變小寫
        System.out.println(str.toLowerCase()); //北京天安門abc
 
        //生成一個新的字符串,字符串的英文字符全部變大寫
        System.out.println(str.toUpperCase());//北京天安門ABC
 
        /*
        註意:String是不可變字符序列,上面的方法改變的隻是新生成的字符串,這裡重新輸出str,依舊是原來的字符
         */
        System.out.println(str);//北京天安門abc
 
 
        //2.2根據索引找子串
        //charAt()方法返回指定索引位置的char值。索引范圍為0~length()-1
        char c = str.charAt(3);//註意下標從0開始
        System.out.println(c);//安
 
        //str.substring(int startIndex);
        //子字符串的下標從索引開始
        System.out.println(str.substring(2));//天安門abc
 
        //substring(int startIndex,int endIndex);
        /*返回一個字符串,該字符串是此字符串的子字符串。
         子串開始於指定beginIndex並延伸到字符索引endIndex- 1
          因此,子串的長度為endIndex-beginIndex
         */
        System.out.println(str.substring(5,8));//abc
 
        // 2.3根據子串找索引
        //public int indexOf(int ch)返回指定字符第一次出現的字符串內的第一個索引
        int index = str.indexOf("abc");
        System.out.println(index);//5
 
        //indexOf(String str, int fromIndex)
        //返回指定子串的第一次出現的字符串中的索引,從指定的索引開始。
        System.out.println(str.indexOf("門", 2));//4
 
        //從後向前查詢第一次遇到的指定字符串的索引位置,註意索引還是從前往後數起
        System.out.println(str.lastIndexOf("北"));//0
 
        // 2.4其他方法
       /* str.concat();
        str.trim();
        str.split();
        str.replace();
        str.replaceAll()等
        */
 
        //split(String regex)
        //split()方法:分割字符串,參數regex稱為分割符,可以使用正則表達式來表示
        String str2 = "Java,HTML,MySQL,Spring,java,Java";
        String arr [] = str2.split("S");
        System.out.println(Arrays.toString(arr));//[Java,HTML,My, QL,, pring,java,Java]
 
        //replace() 方法用於在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串。區分大小寫
        System.out.println(str2.replace("Java","javase"));//javase,HTML,MySQL,Spring,java,javase
 
        //public String replaceAll(String regex,String replacement)
        //用給定的替換替換與給定的regular expression匹配的此字符串的每個子字符串。
        //regex - 要匹配此字符串的正則表達式, replacement - 要替換每個匹配的字
        String str3 = "abc,adc,afffc,rty,acc";
        String str4 = str3.replaceAll("a...c","#");
        System.out.println(str4);//abc,adc,#,rty,acc
 
        //trim()去掉字符串兩邊的空格
        String str5 = "  rbg  ni     men   hao    ";
        System.out.println(str5.length());//27
        System.out.println(str5.trim());//去掉字符串兩端的空格  "rbg  ni     men   hao"
        System.out.println(str5.trim().length());//21
 
        //toCharArray()
        char [] chArr = str.toCharArray();//str = "北京天安門abc"
        System.out.println(chArr);
        System.out.println(chArr[2]);//天
 
 
        //concat()方法,在字符串的末尾追加子串
        String str6 = "北京市";
        str6 = str6.concat("紫禁城").concat("故宮").concat("博物院");
        System.out.println(str6);//北京市紫禁城故宮博物院
        
        //contains() 當且僅當此字符串包含指定的char值序列時,返回true
        System.out.println( str6.contains("博物院"));//true
        
        /*compareTo()方法
        返回比較的前後兩個字符串的ASCII碼的差值,如果兩個字符串首字母不同,則該方法返回首字母的ASCII碼的差值
        如果首字符相同,則比較下一個字符,直到有不同的為止,返回該不同的字符的ASCII碼差值。
        如果兩個字符串不一樣長,可以參與比較的字符又完全一樣,則返回兩個字符串的長度差值。
        返回為正數表示a1>a2, 返回為負數表示a1<a2, 返回為0表示a1==a2
         */
        String str1 = "jsdy";
        String str2 = "jsdr";
 
        System.out.println(str1.compareTo(str2));//7
        
    }
}

例子2:equals和雙等於號==

package li.normalclass.stringclass;
 
public class TestString2 {
    public static void main(String[] args) {
        //equals
        String str1 = new String ("jsdy");
        String str2 = new String ("jsdy");
        System.out.println(str1==str2);//false
        System.out.println(str1.equals(str2));//true
 
        String str3 = "jsdy";
        String str4 = "jsdy";
        System.out.println(str3==str4);//ture!!!
        System.out.println(str3.equals(str4));//true
 
        String str5 = new String ("jsdy");
        String str6 = "jsdy";
        System.out.println(str5==str6);//false
        System.out.println(str5.equals(str6));//true
        
         String str7 = null;//沒有指向任何內容
        String str8 = new String("");
        String str9 = "";//指向一個空字符串
        System.out.println(str9.length());//0
        //System.out.println(str7.length())-->java.lang.NullPointerException
        System.out.println(str8==str9);//false
        System.out.println(str8.equals(str9));//true
 
    }
}

分析:

String str3 = "jsdy";
String str4 = "jsdy";
System.out.println(str3==str4);//ture!!!

采用字面值的方式創建一個字符串時,JVM首先會去字符串池中查找是否存在"jsdy"這個對象,

如果不存在,則在字符串池中創建"jsdy"這個對象,然後將池中"jsdy"這個對象的引用地址返回給"jsdy"對象的引用str3,這樣str3會指向池中"jsdy"這個字符串對象;

如果存在,則不創建任何對象,直接將池中"jsdy"這個對象的地址返回,賦給引用str4。因為str3、str4都是指向同一個字符串池中的"jsdy"對象,所以結果為true。

String str1 = new String ("jsdy");
String str2 = new String ("jsdy");
System.out.println(str1==str2);//false
System.out.println(str1.equals(str2));//true

采用new關鍵字新建一個字符串對象時,JVM首先在字符串池中查找有沒有"jsdy"這個字符串對象,

如果有,則不在池中再去創建"jsdy"這個對象瞭,直接在堆中創建一個"jsdy"字符串對象,然後將堆中的這個"jsdy"對象的地址返回賦給引用str1,這樣,str1就指向瞭堆中創建的這個"jsdy"字符串對象;

如果沒有,則首先在字符串池中創建一個"jsdy"字符串對象,然後再在堆中創建一個"jsdy"字符串對象,然後將堆中這個"jsdy"字符串對象的地址返回賦給str1引用,這樣,str1指向瞭堆中創建的這個"jsdy"字符串對象。str2則指向瞭堆中創建的另一個"jsdy"字符串對象。str1、str2是兩個指向不同對象的引用,結果當然是false。

其他同理。

例子3:

//concat()方法,在字符串的末尾追加子串
        String str6 = "北京市";
        str6 = str6.concat("紫禁城");
        str6 = str6.concat("故宮");
        str6 = str6.concat("博物院");
        System.out.println(str6);//北京市紫禁城故宮博物院

如上圖:

采用字面值的方式創建一個字符串時,JVM首先會去字符串池中查找是否存在"北京"這個對象,如果不存在,則在字符串池中創建"北京"這個對象,然後將池中"北京"這個對象的引用地址返回給"北京"對象的引用str6。使用concat()方法可以追加子字符串,但是String是不可變長序列,所以是實際上是在常量池重新創建瞭一個對象,並把追加的字符串連同原字符串一同賦值給新的對象,然後將新對象的引用地址返回給str6,這樣str6就指向瞭一個新的地址空間。每次使用concat()方法追加子串都會經歷上述過程,str6的指向不斷改變,最終會指向最後一次開辟的對象地址。

因此使用concat()追加子串的方法效率無疑是很低的,那麼有沒有一種辦法可以直接在創建的對象裡添加子串呢?這就是我們要涉及到的StringBuilder類

2.理解String類源碼

String類是一個final類,意味著該類不能有子類

String類底層是一個字符數組value。各種方法的操作其實都是對該數組的操作。

String類的equals()方法其實就是比較底層的字符數組的各個元素是否相同,隻要發現一個元素不同,就返回false,如果所有字符都相同就返回true。但是如果兩個變量都指向瞭同一個字符數組,則直接返回true。

String類的concat()方法是創建一個新的字符數組,存放原來字符數組和新加入的字符數組內容,然後以該新數組創建一個新的字符串。

JDK9時String類底層由char數組變為byte數組,節省空間。同時通過一個coder成員變量作為編碼格式的標識,使用LATIN1還是UFT-16,這個是在String生成時自動的,如果字符串中都是能用LATIN1就能表示的是0,否則就是UFT-16。

3.使用StringBuilder類

StringBuffer和StringBuilder非常類似,均代表可變的字符序列。

這兩個類都是抽象類AbstractStringBuilder的子類,方法幾乎一模一樣

兩個類的主要區別是:

  • StringBuffer JDK1.0提供的類,線程安全,做線程同步檢查,效率較低
  • StringBuilder JDK1.5提供的類,線程不安全,不做線程同步檢查,因此效率較高。建議采用此類

StringBuilder常用函數:

  • append() 向字符串後追加一個子串
  • reverse() 倒置
  • delete() 刪除從start(包含)到end(不包含)位置的字符, start 為0~length-1
  • length() 獲取字符的長度
  • toString() 將StringBuffer轉成String
  • replace() 從start到end之間的字符串替換成新字符串
  • insert() 在指定的偏移量位置插入值
  • indexOf() 從頭開始查找某個字符串在源字符串中第一次出現的位置並返回
  • setCharAt() 設置指定索引位置的字符
  • charAt() 返回指定索引位置上的字符
  • substring() 從start(包含)位置截取字符串返回一個新的String,它包含此序列當前所包含字符的子序列

例子:

package li.normalclass.stringbuilder;
 
/*
    StringBuilder用得比較多的基本上就是這三個常見操作:
    1.創建對象
        StringBuilder builder = new StringBuilder("xxx");
    2.末尾追加字符串
        builder.append("yyy");
    3.轉換為字符串
        String str = builder.toString()
        System.out.println(str)
 */
public class TestStringBuilder1 {
    public static void main(String[] args) {
        //創建StringBuilder對象
 
        /*
        創建Builder對象時,底層的數組大小實際為輸入的字符串長度個數+16
         */
        StringBuilder builder = new StringBuilder("北京");
 
        //length是字符的個數,capacity是底層數組的長度
        System.out.println(builder.length()+"\t"+ builder.capacity());//2  (2+16=)18
 
        //操作StringBuilder對象
        //操作:字符串末尾增加
 
        builder.append("故宮博物院");
        System.out.println(builder.length()+"\t"+ builder.capacity());//7  18
 
        builder.append("墻角下的");
        //---->這裡擴容瞭,擴容方法是:當前字符串長度*2+2,在這裡既是18*2+2=38
        System.out.println(builder.length()+"\t"+ builder.capacity());//11 38
 
        builder.append("一隻懶貓在睡覺覺");
        System.out.println(builder.length()+"\t"+ builder.capacity());//19 38
 
 
        //操作:字符串中間位置增加
        int i = builder.indexOf("下");//找到字符串的數組下標
        builder.insert(i,"一棵銀杏樹");//在下標前插入新的子串
        System.out.println(builder.length()+"\t"+ builder.capacity());//24 38
 
 
        //操作:字符串修改
        int i2 = builder.indexOf("銀杏樹");//找到字符串的數組下標
        builder.replace(i2,i2+3,"芒果樹");//要替換的字符串的起始位置,結束位置,要替換的字符串 :北京故宮博物院墻角一棵芒果樹樹下的一隻懶貓在睡覺覺
 
        //操作:字符串刪除
        builder.deleteCharAt(23);//參數為要刪除的那個字符的索引下標  :北京故宮博物院墻角一棵芒果樹下的一隻懶貓在睡覺
        builder.delete(0,7);//start並延伸到字符索引end - 1:墻角一棵芒果樹下的一隻懶貓在睡覺子串開始於指定
 
        //操作:字符串輸出
        String str = builder.toString();//將StringBuilder轉變為一個字符串
        System.out.println(str);//墻角一棵芒果樹下的一隻懶貓在睡覺
        System.out.println(builder.toString());//墻角一棵芒果樹下的一隻懶貓在睡覺
        System.out.println(builder);//墻角一棵芒果樹下的一隻懶貓在睡覺
        System.out.println(builder.reverse());//覺睡在貓懶隻一的下樹果芒棵一角墻
        System.out.println(builder);//覺睡在貓懶隻一的下樹果芒棵一角墻--->沒有創建新的字符串對象
    }
}

註意實際開發過程中StringBuilder的使用場合:字符串的拼接(SQL語句)

StringBuilder用得比較多的基本上就是這三個常見操作:

//1.創建對象(String-->StringBuilder) 
        StringBuilder builder = new StringBuilder("xxx");
 
//2.末尾追加字符串
        builder.append("yyy");
 
//3.轉換為字符串(StringBuilder--->String)
        String str = builder.toString()
        System.out.println(str);

4.StringBuilder類源碼

StringBuilder的底層就是一個長度可以自動增長的字符數組(JDK9變成瞭字節數組)

StringBuilder類底層和String類一樣,也是一個字符數組value,但不是final的。變量count表示的是底層字符數組的元素的真實個數,不是底層字符數組的長度。

默認數組的長度是16。也可以通過構造方法直接指定初始長度。length()方法返回的是字符數組元素的真實個數,capacity()返回的是底層數組的長度。

添加字符串時如果內存大小不夠要擴容,擴容的默認策略是增加到原來長度的兩倍再加2

快捷鍵Ctrl+Alt+向左箭頭<·····可以實現跳轉到剛剛瀏覽的那個文件的那行代碼

例子1:StringBuilder構造函數

StringBuilder builder = new StringBuilder();
//StringBuilder 的無參構造初始容量為:16

例子2:new StringBuilder

//創建Builder對象時,底層的數組大小實際為輸入的字符串長度個數+16
StringBuilder builder = new StringBuilder("故宮博物院");
System.out.println(builder.length()+"\t"+ builder.capacity());

例子3:toString

String str = builder.toString();
System.out.println(str);

將builder的字符轉換為String字符串

例子4:append()

略。

總結

String:不可變字符序列

StringBuffer:可變字符序列,並且線程安全,但是效率低

StringBuilder:可變字符序列,線程不安全 ,但是效率高(一般用它)

以上就是Java常用類之字符串相關類使用詳解的詳細內容,更多關於Java字符串類的資料請關註WalkonNet其它相關文章!

推薦閱讀: