API之String類

package com.rayNotes;

import org.junit.Test;

/**
 * - 字符串是一個特殊的對象。 - 字符串一旦初始化就不可以被改變。
 * 
 * @author liujun
 * @since 2018.1
 */
public class StringTest {

    /**
     * - str在內存中只有一個對象,str1在內存中有兩個對象。 - test01()
     * :String類複寫了Object類中的equals(),該方法用於判斷字符串的內容是否相同。
     */
    public static void main(String[] args) {
        String str1 = "abcd"; // str是一個類類型變量,"abcd"是一個對象
        String str2 = new String("abcd");

        System.out.println("----------test01---------start---------");
        StringTest st = new StringTest();
        st.test01(str1, str2);// 比較

        System.out.println("----------test02---------start---------");
        String str3 = "abacddd";
        st.test02(str3);// 獲取

        System.out.println("----------test03---------start---------");
        st.test03(str3, str2);// 拼接

        System.out.println("----------test04---------start---------");
        st.test04();// 判斷

        System.out.println("----------test05---------start---------");
        st.test05();// 轉換

        System.out.println("----------test06---------start---------");
        st.test06();// 替換

        System.out.println("----------test07---------start---------");
        st.test07();// 切割

        System.out.println("----------test08---------start---------");
        st.test08();// 子串

        System.out.println("----------test09---------start---------");
        st.test09();//字符串內部轉換、比較
    }

    /**
     * TODO:字符串內部轉換、比較
     */
//  @Test
    public void test09() {
        String str = "a b c d e f g h ij k l m n";

        System.out.println("str.toUpperCase():" + str.toUpperCase());
        String str1 = " c d e f ";
        System.out.println("str1:" + str1.toString());
        System.out.println("str1.trim():" + str1.trim());
        System.out.println("CompareTo()--------");
        String s1 = "abc";
        String s2 = "abcd";
        String s3 = "abcdfg";
        String s4 = "1bcdfg";
        String s5 = "cdfg";
        System.out.println(s1.compareTo(s2)); // -1 (前面相等,s1長度小1)
        System.out.println(s1.compareTo(s3)); // -3 (前面相等,s1長度小3)
        System.out.println(s1.compareTo(s4)); // 48 ("a"的ASCII碼是97,"1"的的ASCII碼是49,所以返回48)
        System.out.println(s1.compareTo(s5)); // -2 ("a"的ASCII碼是97,"c"的ASCII碼是99,所以返回-2)
    }

    /**
     * TODO : 子串
     */
    // @Test
    public void test08() {
        String str = "a b c d e f g h ij k l m n";
        System.out.println("原來的字符串:" + str);
        System.out.println("str.substring(10,12):" + str.substring(10, 12));// 從11 開始,到12結束; 如果超出長度則: 越界異常.
        System.out.println("str.substring(0, str.length()):" + str.substring(0, str.length()));// 從頭到尾
    }

    /**
     * TODO:切割
     */
    // @Test
    public void test07() {
        String str = "a b c d e f g h ij k l m n ";// 最後還有一個空格
        String[] strs = str.split(" ");
        for (String ss : strs) {
            System.out.print(ss + ",");
        }
        System.out.println();
        /**
         * - 如果該限制 n 大於 0,則模式將被最多應用 n - 1 次,數組的長度將不會大於 n。 - 如果 n
         * 爲非正,那麼模式將被應用盡可能多的次數,而且數組可以是任何長度。 - 如果 n 爲
         * 0,那麼模式將被應用盡可能多的次數,數組可以是任何長度,並且結尾空字符串將被丟棄。
         */
        String[] strs1 = str.split(" ", -1);
        for (String ss : strs1) {
            System.out.print(ss + ",");
        }
    }

    /**
     * TODO:替換 String replace(oldchar, newchar);
     */
    // @Test
    public void test06() {
        String s = "hello java";
        // String s1 = s.replace('q', 'n'); // 如果要替換的字符不存在,返回的還是原串
        String oldworld = "java";
        String newWorld = "world";
        String s1 = s.replace(oldworld, newWorld);
        System.out.println("s1.toString():" + s1.toString());
    }

    /**
     * TODO: 轉換
     */
    // @Test
    public void test05() {
        /**
         * - 1. 將 字符數組 轉換成 字符串
         */
        char[] cr = { 'i', 'm', 'a', 'c', 'h', 'a', 'r' };
        String str = "imaString";
        byte[] bt = { 'i', 'm', 'a', 'b', 'y', 't', 'e' };
        /**
         * - 1.1 構造方法:
         */
        String schar = new String(cr);// 底層通過Arrays.copyof()實現
        System.out.println("schar.toString():" + schar.toString());

        final int offset = 2;
        final int count = 3;
        String partChar = new String(cr, offset, count);// cr數據,從offset開始,到count 結束
        System.out.println("partChar.toString():" + partChar.toString());
        /**
         * - 1.2 靜態方法:
         */
        String schar1 = String.copyValueOf(cr, offset, count);
        System.out.println("schar1.toString():" + schar1.toString());
        String scharValue1 = String.valueOf(cr, offset, count);
        System.out.println("scharValue1.toString():" + scharValue1.toString());
        /**
         * - 2. 將字符串轉換成字符數組
         */
        char[] strValue = str.toCharArray();
        System.out.println("strValue.length:" + strValue.length);
        /**
         * - 3. 將字節數組轉成字符串 - 再轉回來
         */
        String strbyte = new String(bt);
        System.out.println("strbyte.toString():" + strbyte.toString());
        System.out.println("str.getBytes():" + str.getBytes());
        /**
         * - 4. 基本數據類型轉成字符串 - 通過 valueOf() - 10 +"" == String.valueOf(10); int--->String
         */
    }

    /**
     * TODO:判斷
     * 
     * @param str
     * @param str2
     */
    // @Test
    public void test04() {
        String str = "StringTest.java";

        System.out.println("str.isEmpty():" + str.isEmpty());// 原理就是判斷長度是否爲0,是否空
//      特殊之處:indexOf(str):可以索引str第一次出現的位置,如果返回-1,表示該str不在字符串中存在,
//              所以,也可以用於對指定字符串判斷是否包含,而且該方法既可以判斷,又可以獲取出現的位置。
        System.out.println("str.contains(\"Test\") :" + str.contains("Test"));// 是否包含該String

        int toffset = 0;
        String strPart = "String";
        System.out.println("str.startsWith(strPart, toffset): " + str.startsWith(strPart, toffset));// 從 toffset 開始,是否以
                                                                                                    // strPart 開頭

        String strEnd = ".java";
        System.out.println("str.endsWith(strEnd):" + str.endsWith(strEnd));// 字符串是否是以指定內容結尾

        String str2 = "stringtest.java";
        System.out.println("str.equals(str2):" + str.equals(str2));// 比較 值 是否 same
        System.out.println("str.equalsIgnoreCase(str2):" + str.equalsIgnoreCase(str2));// 同上,忽略大小寫
    }

    /**
     * TODO: 拼接
     * 
     * @param str,str2
     */
    // @Test
    public void test03(String str, String str2) {
        /**
         * - 1、+ - 2、concat - 當兩個量都爲String類型且值不爲null時,可以用concat方式。 - 3、append -
         * 當需要拼接至少三個量的時候,StringBuffer#append() 以避免臨時字符串的產生
         * 
         * - StringBuffer大多數情況(包括append操作)線程安全。 -
         * 若不會出現多線程同時對一實例併發進行append操作,建議使用非線程安全的StringBuilder以獲得更好性能 StringBuffer
         * buf=new StringBuffer() buf.append("a"); if(someCondition){ buf.append("b"); }
         * buf.append("c"); String d=buf.toString();
         */
        //
        System.out.println(str + str2);

        System.out.println(str.concat(str2));

        StringBuffer strb = new StringBuffer();
        System.out.println(strb.append(str2).append(str).toString());

        StringBuilder strd = new StringBuilder();
        System.out.println(strd.append(str2).append(str).toString());

        /**
         * 引用 <https://www.cnblogs.com/Wfei/p/3248922.html>
         * StringBuffer.append()所改變的是源引用的值,不會依賴於方法返回值,
         * 而String.concat()在進行字符串拼接的時候,會產生很多的臨時對象來保存
         *
         * - 最後在拼接結束後,需要把這個結果臨時對象進行返回給接收值進行再指向, 需要依賴於方法的返回值,執行的效率也會隨着字符數的增加而降低,不是真正的引用源
         * 總結: - 在所使用的字符串需要經常變更的情況下,使用StringBuffer效率更高,
         * 可以使用StringBuffer進行字符串的變更操作,操作完成後再還給String, - 操作方法:String -> StringBuffer ->
         * 更改字符串 -> String
         */
        forTest03Change(str, strb);
        System.out.println(str);
        System.out.println(strb);

        /**
         * 拓展: 字符串拼接共五種方法: 1. 加號 “+”
         * 
         * 2. String contact() 方法
         * 
         * 3. StringUtils.join() 方法
         * 
         * 4. StringBuffer append() 方法
         * 
         * 5. StringBuilder append() 方法
         *
         *
         * 1. 方法1 加號 “+” 拼接 和 方法2 String contact() 方法 適用於小數據量的操作,代碼簡潔方便,加號“+”
         * 更符合我們的編碼和閱讀習慣;
         * 
         * 2. 方法3 StringUtils.join() 方法
         * 適用於將ArrayList轉換成字符串,就算90萬條數據也只需68ms,可以省掉循環讀取ArrayList的代碼;
         * 
         * 3. 方法4 StringBuffer append() 方法 和 方法5 StringBuilder append() 方法
         * 其實他們的本質是一樣的,都是繼承自AbstractStringBuilder,效率最高,大批量的數據處理最好選擇這兩種方法。
         * 
         * 4. 方法1 加號 “+” 拼接 和 方法2 String contact() 方法 的時間和空間成本都很高(分析在本文末尾),不能用來做批量數據的處理。
         *
         *
         * 1、其實每次調用contact()方法就是一次數組的拷貝,雖然在內存中是處理都是原子性操作,速度非常快, -
         * 但是,最後的return語句會創建一個新String對象,限制了concat方法的速度。
         * 
         * 2、StringBuffer 和 StringBuilder 的append方法都繼承自AbstractStringBuilder,
         * 整個邏輯都只做字符數組的加長,拷貝,到最後也不會創建新的String對象,所以速度很快,
         * 完成拼接處理後在程序中用strBuffer.toString()來得到最終的字符串。
         * 
         * 
         * 3、 字符串的加號“+” 方法, 雖然編譯器對其做了優化,使用StringBuilder的append方法進行追加,
         * 但是每循環一次都會創建一個StringBuilder對象,且都會調用toString方法轉換成字符串,所以開銷很大。 - 注:執行一次字符串“+”,相當於
         * str = new StringBuilder(str).append("a").toString(); - 循環使用則 直接使用builder
         * ,其餘情況 +
         * 
         * 4、 本文開頭的地方統計了時間開銷,根據上述分析再想想空間的開銷。常說拿空間換時間,反過來是不是拿時間換到了空間呢,
         * 但是在這裏,其實時間是消耗在了重複的不必要的工作上(生成新的對象,toString方法), 所以對大批量數據做處理時,加號“+” 和 contact
         * 方法絕對不能用,時間和空間成本都很高。
         *
         * 
         * String:適用於少量的字符串操作的情況
         * 
         * StringBuilder:適用於單線程下在字符緩衝區進行大量操作的情況
         * 
         * StringBuffer:適用多線程下在字符緩衝區進行大量操作的情況(99.99999%情況下不用)
         */
    }

    public void forTest03Change(String str, StringBuffer str2) {
        str.concat("contact");
        str2.append("append");
    }

    /**
     * TODO: 獲取
     * 
     * @param str
     */
     @Test
    public void test02(String str) {
//       abacddd
        int localAt = 2;
        int fromIndex = 1;
        String strLocalAt = "a";
        System.out.println(str.charAt(localAt));// 根據位置獲取位置上某個字符 ,從0 開始計數

        // 索引,即使越界也沒事,找不到返回 -1(也可藉此來直接用來判斷),不存在該位置 則略過
        // System.out.println(str.contains("a"));//字符串中是否包含某一個子串:boolean

        System.out.println(str.indexOf(strLocalAt, fromIndex));// 返回的是 從fromIndex指定位置開始 ,strLocalAt/localAt
                                                                // 在字符串中第一次出現的位置
        System.out.println(str.lastIndexOf(strLocalAt, fromIndex));// 反向
    }

    // @Test
    public void test01(String str1, String str2) {
        System.out.println(str1 == str2);// false,比較的對象
        System.out.println(str1.equals(str2));// true,比較的值
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章