不少人喜欢在前面加入赘述,事实上去技术网站找相关的内容的通常都应当已经对相应知识有必定了解,所以我再也不过多赘述字符串究竟是什么东西,在官网中已经写得很明确了,字符串其实是一种特殊的类,内置了一个字符数组(因此你能对它进行下标查找,包括集合的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 }
漏洞百出,懒惰至极,建议当场出柜【划掉】。