不少人喜歡在前面加入贅述,事實上去技術網站找相關的內容的通常都應當已經對相應知識有必定了解,所以我再也不過多贅述字符串究竟是什麼東西,在官網中已經寫得很明確了,字符串其實是一種特殊的類,內置了一個字符數組(因此你能對它進行下標查找,包括集合的arraylist底層也是一個數組),並附加了不少其餘方法,方便咱們進行一些操做。有興趣的話能夠去百度中查閱相關內容。我事先說好了,本文只是我用來回憶和複習的一個粗略筆記,以及一些實驗代碼。若是須要學習Java,建議去慕課網或者雲課堂。java
Java的類基本上都繼承於Object類,也就是都繼承了其中的tostring方法,來標識其指向的地址,這是由於Java對象名稱實際上只是一個引用,真正的東西還在堆中。Java的理念來源於C艹,可是字符串的運算符實際上不是重載而是在jvm中動了手腳,Java中任何運算符都不能重載!要細究這個問題就要探究JVM,我對Java虛擬機也是隻知其一;不知其二,因此就不豬鼻子插蔥了。c++
1.1Java的相關入門基礎正則表達式
1 package TheUnity5; 2 //java中的字符串鏈接經過運算符加號完成,他方便了在字符串換行時候的鏈接 3 public class Demo1 { 4 public static void main(String[] args){ 5 String str="the java like skr rap"; 6 String str2="the java like " 7 + "skr2 rap";//java編譯器不容許一個字符串跨越兩行 8 System.out.println(str); 9 System.out.println(str2);//一個顯示效果 10 11 System.out.println("--------------------"); 12 13 Boolean str3=Boolean.valueOf(false); 14 System.out.println(""+str3);//string鏈接數據類型 15 16 Object str4=new Object(); 17 System.out.println(str4.toString()); 18 //經過對照說明了封裝類其實內部已經對tostring進行了重寫 19 } 20 }
而事實上不少類的tostring也進行了重寫,格式化輸出的其實是類的tostring方法算法
Java內置了字符串的檢索方法indexof,這個方法通過了重載,容許字符和字符串做爲參數,且可以指定檢索的起始位置,須要注意的是他會返回取到的第一個匹配值而後結束若是你須要檢索全部內容你須要進行一個循環判斷,而這個方法當你檢索的位置超出時,會產生負值。所以在循環判斷的過程當中,須要注意不少因素。固然你也能夠一個一個用charAt去截取而後再去判斷,事實上從算法的時間複雜度來講,這兩個傢伙都是遍歷,壞的很。數組
1.2Java檢索指定字符串的出現位置安全
1 package TheUnity5; 2 //這裏總結字符串的相關檢索方法 3 public class Demo2 { 4 public static void main(String[] args){ 5 String str="do you like van♂ 遊戲?"; 6 System.out.println(str); 7 System.out.println("------------------"); 8 System.out.println("length:"+str.length()); 9 System.out.println(str.indexOf('o'));//這裏返回的是第一個O的位置。 10 System.out.println(str.indexOf('o',str.length()-1));//這裏返回從2開始的第一個o的位置,包括2也在檢索範圍內 11 12 //若是想要得到全部的指定字符的位置,只能經過循環的方式 13 talk1(str,'o'); 14 talk2(str,'o'); 15 } 16 //經過對每個字符進行匹配肯定位置 17 public static void talk1(String str,char ch){ 18 int size=str.length(); 19 for(int i=0;i<size-1;i++){ 20 char a=str.charAt(i); 21 if(a==ch){ 22 System.out.print(i+" "); 23 } 24 } 25 System.out.println("talk1結束"); 26 } 27 //實際上indexof底層也是遍歷匹配,可是對安全性作了不少措施 28 public static void talk2(String str,char ch){ 29 int i=0; 30 do{ 31 i=str.indexOf(ch,i); 32 if(i==str.lastIndexOf(ch)){ 33 System.out.print(i+" "); 34 break; 35 } 36 if(i>=0){ 37 System.out.print(i+" "); 38 i++;//注意這個位置 39 } 40 }while(i>=0); 41 System.out.println("talk2結束"); 42 } 43 }
Java其實是開發者由於感覺寫一個機頂盒c++程序很是煩躁下,開發出的一款語言。很是隨意,就和它的名字來源於當時喝的咖啡(其實原本是另一種咖啡可是名字已經被註冊了23333)。所以重複的字符數組裁剪工做被封裝成了對應的方法,這就很nice了,常見的操做有字符串的分割,截取,替換,去空格等,下面是相關的代碼實現和結果。(懶癌入髓,不過這也可以起到讓大家認真看代碼的效果【義正詞嚴.jpg】)多線程
1.3Java的字符串操做併發
1 package TheUnity5; 2 //Java中內置了一些對字符串的相關操做。方便對字符串進行修改 3 public class Demo3 { 4 public static void main(String[] args){ 5 //初始字符串 6 String str=" deep♂ dark♂ fantasy "; 7 //字符串截取方法substring會產生一個臨時的字符串副本,本質上不會改變原來的字符串 8 String str1=str.substring(5); 9 String str2=str.substring(5,11);//不包含第二參數 10 System.out.println(str); 11 System.out.println(str1); 12 System.out.println(str2); 13 System.out.println("------------------------"); 14 //去除首尾空格,Java的trim方法不會去除字符串內部的非首尾空格 15 String str3=str.trim(); 16 System.out.println(str3+" "+str.length()+" "+str3.length()); 17 System.out.println("------------------------"); 18 //字符串替換中Java內置了replace方法,但不建議使用由於他會將原字符串因此相同部分所有替換 19 String str4=str.replace('♂', ' '); 20 System.out.println(str); 21 System.out.println(str4); 22 String str5=change(str,"♂"," ",0,str.length()); 23 String str6=change(str,"♂"," ",str.indexOf("♂")+1,str.length()); 24 System.out.println(str5); 25 System.out.println(str6); 26 System.out.println("------------------------"); 27 //java同時也內置了一些字符串開頭和結尾的驗證,但事實上你會發現大部分字符串的操做方法你均可以本身去從新定義 28 System.out.println(str.startsWith("deep")); 29 System.out.println(str.startsWith("deep",1)); 30 System.out.println(str.endsWith("fantasy")); 31 System.out.println(str.endsWith("fantasy ")); 32 //從輸出結果來看,空格也被包含進去了 33 System.out.println("------------------------"); 34 //Java也有字符串的大小寫轉換,能夠參考咱們自定義的替換方法思考他是怎麼作到的。 35 String str7=str.toUpperCase(); 36 String str8=str.toLowerCase(); 37 System.out.println(str7); 38 System.out.println(str8); 39 System.out.println(str7.compareTo(str8));//順帶提一下,有興趣能夠本身百度 40 System.out.println("------------------------"); 41 //字符串分割 42 String[] sp=str.split("♂"); 43 talk(sp); 44 sp=str.split("♂", 2);//後面表示分割爲幾份 45 talk(sp); 46 sp=str.split(" "); 47 talk(sp);//這樣能去除全部空格,注意第一個位置爲空字符串而不是空。 48 System.out.println("------------------------"); 49 } 50 //自定義字符串替換 51 public static String change(String str,String demo,String demo2,int startindex,int endindex){ 52 String s1=str.substring(0, startindex); 53 String s2=str.substring(startindex, endindex); 54 String s3=str.substring(endindex); 55 s2=s2.replace(demo, demo2); 56 String s=s1+s2+s3; 57 return s; 58 } 59 60 public static void talk(Object[] objs){ 61 for(int i=0;i<objs.length;i++){ 62 System.out.print("["+objs[i]+"] "); 63 } 64 System.out.println(); 65 } 66 }
若是你在高併發的環境下和咱們的demo中同樣寫,那麼恭喜你,你明天能夠去人事部結一下工資了。事實上原始的string不光效率不高,並且上述方法都會產生一段字符串對象,Java中string很是特殊,若是你直接賦值給一個引用一段字符串,那麼它會先去常量區尋找,若是找不到那麼就會將該字符串注入常量池,下次再引用的時候就會直接指向常量池中的內容。而若是是經過new出一段字符串對象,那麼它會將你放進推中,而且不會去理你,除非我對這段對象進行操做。app
1.4Java字符串內存位置jvm
1 package TheUnity5; 2 //Java字符串的內存問題 3 public class Demo4 { 4 public static void main(String[] args){ 5 //對於String,若是你對Java底層的代碼有過了解會知道,實際上是一個封裝的char數組 6 //並且,是被final修飾的,因此只能賦值一次,String的內容實際是在常量池中的 7 String str="神奇的沙德沃克先生"; 8 String s1="神奇的沙德沃克先生"; 9 System.out.println(str==s1); 10 //輸出true,說明str與s1指向了同一內存地址 11 //若是不建立新的字符串對象,相同內容的賦值其實是多個引用指定一個內存【證實常量池的存在】 12 System.out.println("------------------------"); 13 String s2=new String("神奇的沙德沃克先生"); 14 System.out.println(s2==str); 15 System.out.println(s2.equals(str)); 16 //打印結果很明顯是內容相同內存不一樣,這裏string對象存在堆中 17 System.out.println("------------------------"); 18 String s3="神奇的沙德沃克先生"; 19 System.out.println(str==s3); 20 System.out.println(s2==s3); 21 //仍然指向最先定義的字符串常量 22 } 23 }
1.5對比試驗
1 package TheUnity5; 2 3 public class Demo5 { 4 public static void main(String[] args){ 5 //這裏接demo4繼續討論 6 String str=new String("ABC"); 7 String s1="ABC"; 8 System.out.println(s1==str); 9 //輸出結果爲false,證實new 一個string對象實際上避免了在常量池注入常量 10 //而事實上String的大部分方法都會返回一個新的string對象,在程序開發中確實確保了安全性 11 //但事實上咱們須要的不是堆中內存分配的過渡浪費。 12 } 13 }
重點來了,你可能也據說過jvm的對象銷燬機制,它是由虛擬機本身決定何時銷燬的,這就會致使堆中對象不斷累加,常規開發環境沒什麼問題,可是若是是高併發開發那麼就會產生很大的內存開銷,這是不明智的。Java的開發者也想到了這個問題,因此提出了stringbuffer,提供線程安全的string加強類。在後續開發中在非併發中又開發了stringbuild類,固然後者是線程不安全的,可是性能更高。對這兩種加強類的操做不會產生新的對象,所以節省了堆的開銷。
1.6兩種加強類
1 package TheUnity5; 2 //這裏開始正式講string的兩種拓展,他們都是在原對象上進行修改,達到節省空間的效果 3 public class Demo6 { 4 public static void main(String[] args){ 5 //Stringbuild 6 System.out.println("---------------------"); 7 StringBuilder sb=new StringBuilder("NMSL"); 8 StringBuilder sb1=new StringBuilder(" CNM"); 9 sb.append(sb1);//在後部添加 10 System.out.println(sb.toString()); 11 sb.insert(0, "髒魚 ");//指定位置插入 12 System.out.println(sb.toString()); 13 sb.delete(0, 3); 14 System.out.println(sb.toString()); 15 System.out.println("---------------------"); 16 StringBuffer sf=new StringBuffer("NMSL"); 17 sf.append(" CNM"); 18 //stringbuffer同上,並且更安全。 19 System.out.println(sf.toString()); 20 //事實上是先有的StringBuffer,而後有的StringBuild,在多線程中前者安全後者不 21 //在單線程中後者比前者性能更好 22 } 23 }
正則表達式其實是一種規範,在不一樣的語言會有些許不一樣,而Java中採用類對其進行處理,具體的語法能夠參考各個技術論壇。PS:我是真的煩背書T_T,若是開發要用到這個,我可能得去翻相關的文檔,實在記不住。
1.7Java正則表達式的兩種用法
1 package TheUnity5; 2 3 import java.util.regex.Matcher; 4 import java.util.regex.Pattern;//Java正則表達式包 5 6 //嚴格意義來講正則表達式並非一種語言,而是一種規範,不一樣語言在部分地方有細微查異 7 //本文只對Java的正則表達式討論 8 public class Demo7 { 9 public static void main(String[] args){ 10 String content="風見嘯大勝利!"; 11 String par=".*勝利.*"; 12 boolean isMatch = Pattern.matches(par,content); 13 System.out.println(isMatch); 14 System.out.println("--------------------"); 15 String content2="15270003639"; 16 String par2="1[358]\\d{9}"; 17 boolean isMatch2=content2.matches(par2); 18 System.out.println(isMatch2); 19 //以上是正則表達式的兩種寫法,更多的內容推薦從菜鳥教程這些網站中學習 20 } 21 }
漏洞百出,懶惰至極,建議當場出櫃【劃掉】。