java中常用類String見解

字符串操作是計算機程序設計中最常見的行爲,所以掌握好String類的使用很重要。
String是一個final修飾的類,所以它是不可以被繼承的,String對象是不可以變的,也就是說創建了一個對象以後,那麼這個對象的長度是不可以修改的,而我們平時進行的字符串拼接、修改等操作都只是拷貝了它的引用,並不會改變原字符串的大小。
下面通過一段代碼來了解一個String的創建對象;

       //創建String對象
        String str="yxc";
        String str2="yxc";
        String str1=new String("yxc");
        String str3=new String("yxc");
        System.out.println(str1==str3);
        System.out.println(str==str2);
        System.out.println(str==str1);

返回結果:
false
true
false
可能初學者有點困惑,那麼下面通過圖解來分析(還在尋找合適的畫圖軟件,暫時手動畫:)

在這裏插入圖片描述 首先對於str和str2來說,在常量池創建一個“yxc”常量,然後將它的地址給str,str2.
而str1和str3來說,首先使用new關鍵字在堆內存在創建一個對象,然後把堆內存的引用傳給str1和str3 而後面傳進來的參數是常量池中的引用。
再看下面的一段代碼:

       String str1="hello world";
       String str2=str1.substring(2);
       System.out.println(str2);
       System.out.println(str1);

運行結果:
llo world
hello world
對於substring函數是截取字符串,後面的參數表示索引,從哪開始截取,這個我們後續再說,這裏想要說的是,我們修改了通過str.substring(),但是原來的字符串str1其實根本沒有改變,這就是字符串的不可變成,其實這種設計正是我們需要的,很多時候我們不希望修改原來的值。對於字符串中的函數通常都是如果操作成功返回一個新的對象,如果沒有就返回原來的對象,這樣節約了很多空間,怎麼說的,看下面代碼:

       tring str1="hello world";
       String str2=str1.substring(0);
       String str3=str1.substring(1);
       System.out.println(str1==str3);
       System.out.println(str1==str2);

結果返回:
false
true
對吧,這就說明了返回原對象和返回一個新的對象。字符竄中很多方法都是這樣設計的,下面我們學習一下String中常用的方法。通過一段代碼加上詳細的註釋直接搞定:

package com.yxc.string;
//測試String中常見的方法
public class StringProject {
    public static void main(String[] args) {
        System.out.println("其它數據類型轉爲String類型測試");
       //將其它數據類型轉爲字符串
        double d=123456.7;
        String str1 = String.valueOf(d);
        System.out.println(str1);   //123456.7
        //其它的數據類型都是一樣的,只是換一下數據類型就可以
        //這裏還有一種稍微特殊一點的
        char[] c=new char[]{'a','y','z','w'};
        //從下標爲1開始截取,截取兩個,然後將這兩個轉換爲字符串
        String str2 = String.valueOf(c, 1, 2);
        System.out.println(str2);    //yz


        System.out.println("字符串轉爲其它數據類型");
        String str3="3121";
        int j = Integer.parseInt(str3);
        System.out.println(j);   //3121
        //其它的數據類型類似

        System.out.println("計算字符串長度");
        System.out.println(str3.length());//注意length是方法,不是數據中的屬性

        System.out.println("字符串開頭和結尾 返回boolean類型");
        String str4="jamesy";
        System.out.println(str4.startsWith("j"));//true
        System.out.println(str4.endsWith("k"));   //false

        System.out.println("索引");
        /**
         * 索引元素,如果存在返回字符串所在的下標,下標從零開始 如果不存在返回-1
         * 如果是從後面索引,如果找到也是返回下標嗎,而是是從前往後的下標(注意)
         * 如果有相同的就返回第一個查找的的
         */
        String str5="I will give you some color to see see";
        System.out.println(str5.indexOf("give"));
        System.out.println(str5.lastIndexOf("give")); //返回結果也是7
        System.out.println(str5.indexOf("see"));           //30
        System.out.println(str5.lastIndexOf("see"));  //34
        //所以索引see的時候肯定是不一樣的,從前往後索引和從後索引第一個出現的see的位置不一樣

        System.out.println("忽略大小寫比較");
        System.out.println("hello".equalsIgnoreCase("HeLLo"));//true

        System.out.println("根據位置索引值");
        System.out.println("asdfg".charAt(3)); //f

        System.out.println("將字符串轉爲字符數組");
        String str6="just do it";
        char[] chars = str6.toCharArray();
        for(int i=0;i<chars.length;i++){
            System.out.print(chars[i]);
        }

        System.out.println("截取字符串");
        String str7="justsoso";
        String substring = str7.substring(2, 5);  //sts 2截取到5
        System.out.println(substring);

        System.out.println("連接字符串");
        System.out.println("yxc".concat("xin"));

        System.out.println("將字符串轉爲字節數組");
        String str8="yuio";
        byte[] bytes = str8.getBytes();
        for(int i=0;i<bytes.length;i++){
            System.out.print(bytes[i]+" ");  //121 117 105 111
        }

        System.out.println("是否包含某一個對象");
        String str9="yangxinchun";
        String str10="xin";
        System.out.println(str9.contains(str10));  //true

    }
}

String類確實經常使用,但是有些情況使用它的效率會很低,看下面一段代碼:

        long startTime = System.currentTimeMillis();
        String str="yxc";
        for(int i=1;i<100000;i++){
            str=str+i;
        }
        long endTime=System.currentTimeMillis();
        System.out.println(endTime-startTime);

在我機器上硬是跑了40977ms,(我測試了下10000000,幾分鐘沒跑出來我就關閉了)這才十萬級別,而且更可怕的是上面的操作會產生十萬多個對象。這樣的效率太低而且消耗資源,因爲對象的創建是很耗資源的,只是爲了拼接一個字符上去就要產生一個新的對象,這樣的設計顯然不和實際,所以java中有加強String類中字符串拼接的類,StringBuffer和StringBuilder,同樣我們測試一下時間:

        long startTime = System.currentTimeMillis();
        String str="yxc";
        StringBuilder str1=new StringBuilder(str);
        for(int i=1;i<100000;i++){
            str1.append(i);
        }
        long endTime=System.currentTimeMillis();
        System.out.println(endTime-startTime);

耗時27ms

        long startTime = System.currentTimeMillis();
        String str="yxc";
        StringBuffer str1=new StringBuffer(str);
        for(int i=1;i<100000;i++){
            str1.append(i);
        }
        long endTime=System.currentTimeMillis();
        System.out.println(endTime-startTime);

耗時33ms,所以可以看出來,在字符串拼接上面,後兩者的效率提高的不只是幾個檔次了,而對於後面兩者StringBuilder的效率還會高一點,但是它是線程不安全的,而Stringbuffer是線程安全的。

 StringBuffer str=new StringBuffer("abcdefg");
        //stringbuffer中常見的方法

        System.out.println("插入一個元素在字符串中");
        StringBuffer str1 = str.insert(2, "poi");
        System.out.println(str1);   //abpoicdefg
        //和String不一樣,str的值發生了改變
        System.out.println(str);  //abpoicdefg
        //也就是說兩者的對象時一樣的
        System.out.println(str==str1);  //true

        System.out.println("字符串的反轉");
        System.out.println(str.reverse());   //gfedciopba

        System.out.println("字符串的刪除");
        StringBuffer str3 = str.delete(3, 6);
        System.out.println(str3);  //gfeopba

StringBuilder和StringBuffer是一樣的,而且String有的方法這兩個類基本也有,可以看成是對於String的擴展類,但是不是繼承,因爲String是final修飾的類,不能被繼承。注意上面的代碼操作的都是一個對象,修改以後,StringBuffer的對象一直在改變。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章