String类
String类
(一). 认识String
字符串是一个特殊的对象,一旦初始化就不可改变。
有两种方式定义一个字符串对象:
(1)String str = “abc”; //它在执行时是在字符串常量池中创建一个对象,并把地址赋给引用型变量
(2)String str1 = new String("abc");//它在执行时是在堆内存中,创建了两个对象,用new方式创建了一个字符串对象;紧接着在构造时,又接收了一个字符串对象。
String s = new String();//等效于String s = “”; //不等效于String s = null; 因为前两者都是创建了一个空的字符串,最后一个是常量值空
特别注意两者的区别:
虽然str、str1的值都为“abc”,但是其引用地址是不一样的。所以str不等于str1,但是如果定义String str2 = “abc”;这时如果将str2与str比较,两者是等同的,因为
当在字符串常量池中创建对象时,会先查找该常量池中是否存在该内容,如果存在就直接把引用地址赋给变量,如果池中不存在才新建一个。
1.1 String功能
(1)获取(牢记)
- 获取字符串长度:int length() //注意在数组中length是属性,但在string中length是方法
- 根据位置获取字符:char charAt(int index);
- 根据字符获取字符在字符串中第一次出现的位置:int indexOf(int char);//可以放整形,或者char类型,都可以解析出来
- 从指定位置查找字符在字符串中第一次出现的位置:int indexOf(int char,int fromIndex);
- 获取子字符串在字符串中第一次出现的位置:int indexOf(String str);
- 从指定位置查找子字符串在字符串中的位置:int indexOf(String str,int fromIndex);
- 返回指定字符在字符串中最后一次出现的位置:int lastIndexOf(int char);
- 返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索:int lastIndexOf(int char,int fromIndex);
- 返回指定字符串在字符串中最后一次出现的位置,反向索引:int lastIndexOf(String str);
- 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索:int lastIndexOf(String str,int fromIndex);
- 获取字符串的子串:String substring(int beginIndex,int endIndex); //包含开始,不包含结尾
实践见真知
1 public class StringDemo { 2 public static void main(String[] args){ 3 StringPracticeDemo(); 4 } 5 public static void StringPracticeDemo() { 6 String s = "abcdefeagkl"; 7 System.out.println("length:"+s.length());//10 8 System.out.println("At:"+s.charAt(4));//e 9 System.out.println("indexOf:"+s.indexOf('k'));//8 10 System.out.println("indexOf:"+s.indexOf('m') );// 11 //indexOf有两个作用,1是索引位置,2是判断存在,如果不存在就返回-1,我们可以通过返回值来判断该字符存在不存在 12 System.out.println("lastIndexOf:"+s.lastIndexOf('a'));//7 13 System.out.println("indexOf str:"+s.indexOf("def"));//3 14 System.out.println("lastIndex str:"+s.lastIndexOf("eag"));//6 15 16 //获取子串 17 System.out.println("substring:"+s.substring(6)); 18 //包含开始,不包含结尾 该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符 19 System.out.println("substring:"+s.substring(6,9)); 20 } 21 }
(2)转换
- 把字符串变成字符串数组(字符串切割):String[] split(regex);//设计到正则表达式
- 字符串变成字符数组:char[] toCharArray();
- 字符串变成字节数组:byte[] getBytes();
- 字符串字母转换大小写:String toUpperCase(); String toLowerCase();
- 将字符串中的内容进行替换:String replace(ch oldCh,ch newCh);//如果替换成功返回一个新串(因为字符串一初始化就已经固定),如果替换不成功则返回原字符串。
- 字符串进行替换:String replace(String str1,String str2);// 后者替换前者
- 去除字符串两端的空格:String trim();
- 将字符串进行连接:String concat(String str);
- 将基本数据类型变成字符串:String valueOf();
实践见真知
1 public class StringDemo { 2 public static void main(String[] args){ 3 StringPracticeDemo1(); 4 } 5 public static void StringPracticeDemo1() { 6 //字符串切割 7 String str = "张三,李四,王五"; 8 String[] names = str.split(","); 9 for(String name : names){ 10 System.out.println(name); 11 } 12 //字符串转字符数组 13 String str1 = "abcdef"; 14 char[] ch = str1.toCharArray(); 15 for(int i=0;i<ch.length;i++){ 16 if(i<ch.length-1){ 17 System.out.print(ch[i]+","); 18 }else{ 19 System.out.println(ch[i]);//a,b,c,d,e,f 20 } 21 } 22 //字符串转字节数组 23 byte[] by = str1.getBytes(); 24 for(int i=0;i<by.length;i++){ 25 if(i<by.length-1){ 26 System.out.print(by[i]+","); 27 }else{ 28 System.out.println(by[i]);//97,98,99,100,101,102 29 } 30 } 31 //字符串大小写转换 32 System.out.println(str1.toUpperCase());//ABCDEF 33 System.out.println("AVBCD".toLowerCase());//avbcd 34 //字符串连接 35 String str2 = str1.concat("abc"); 36 System.out.println(str2);//abcdefabc 37 //字符串替换 38 String str3 = str2.replace("abc", "cba"); 39 // String str3 = str2.replace("abd", "cba");//abcdefabc如果找不到则返回原串 40 System.out.println(str3); 41 //去除字符串两端空格 42 String str4 = " -abc d- "; 43 System.out.println(str4.trim());//-abc d- 44 //将基本数据类型转换为字符串 45 int c = 5+1; 46 String b = ""; 47 System.out.println("b="+b.valueOf(c));//b=6 48 } 49 }
(3)判断
- 判断字符串是否相同:boolean equals(Object obj); boolean equalsIgnoreCase(String str);//忽略大小写进行比较
- 字符串中是否包含子字符串:boolean contains(String str); 可以用indexOf来替换,返回-1代表不包含
- 字符串是否以指定字符串开头,是否以指定字符串结尾:boolean startsWith(string); boolean endsWith(string);
实践见真知
1 public class StringDemo { 2 public static void main(String[] args){ 3 StringPracticeDemo2(); 4 } 5 public static void StringPracticeDemo2() { 6 //比较,忽略大小写比较 7 String s1 = "abc"; 8 String s2 = "ABC"; 9 System.out.println(s1.equals(s2));//false 10 System.out.println(s1.equalsIgnoreCase(s2));//true 11 12 //是否包含某个字符串 13 String s3 = "abcdfaf"; 14 System.out.println(s3.contains("cdfe"));//false 15 16 //是否以指定字符串开始,已制定字符串结尾 17 String s4="Hello.java"; 18 System.out.println(s4.startsWith("Hel"));//true 19 System.out.println(s4.endsWith(".java"));//true 20 } 21
(4)比较
- 比较两个字符串的大小(按照字典顺序):int compareTo(String anotherString) //如果参数字符串等于此字符串,则返回值
0
;如果此字符串按字典顺序小于字符串参数,则返回一个小于0
的值;如果此字符串按字典顺序大于字符串参数,则返回一个大于0
的值。 - 返回字符串的规范化表示形式:String intern();
实践见真知
1 public class StringDemo { 2 public static void main(String[] args){ 3 StringPracticeDemo3(); 4 } 5 public static void StringPracticeDemo3() { 6 String s6 = new String("alsjf"); 7 String s7 = "asvsd"; 8 System.out.println(s6.compareTo(s7));//-7 s6小于s7 9 10 String s8 = s6.intern(); 11 System.out.println(s6==s8);//false 是因为intern方法是从字符串池中创建,而s6是在堆内存中 12 }
(二). StringBuffer字符串缓冲区(可变长度数组)
2.1 StringBuffer特点
- StringBuffer是一个可变长度的容器
- 可以存储不同类型数据
- 最终要转成字符串进行使用(输出的全是字符串,最终用的时候都是变成字符串才能取用)
- 可以对字符串进行修改
2.2 StringBuffer功能
2.2.1 添加功能
- StringBuffer append(Data)————往容器中添加数据
- StringBuffer insert(index,data)————在某个位置上插入数据
实践见真知
1 public class StringBufferDemo { 2 public static void main(String[] args) { 3 StringBuffer sb = new StringBuffer(); 4 //添加功能 5 sb.append(9+"11").append("nihao");//添加链 6 sb.append(true); 7 System.out.println(sb);//911nihaotrue 8 //插入功能 9 sb.insert(3, "hehe"); 10 System.out.println(sb);//411hehenihaotrue 11 } 12 }
2.2.2 删除功能
- StringBuffer delete(start,end)————删除缓冲区中的元素,指定开头,不包含结尾
- StringBuffer deleteCharAt(int index)————删除指定位置上的元素
实践见真知
1 public class StringBufferDemo { 2 public static void main(String[] args) { 3 Demo_2(); 4 } 5 public static void Demo_2() { 6 StringBuffer sb = new StringBuffer(); 7 sb.append("abcdefgh"); 8 sb.deleteCharAt(3);//删除指定位置上的字符 9 System.out.println(sb);//abcefgh 10 sb.delete(2, 5);//删除包含头元素,不包含尾元素 11 System.out.println(sb);//abgh 12 sb.delete(0, sb.length());//该方法是清空缓冲区 13 System.out.println(sb.length());//0 14 } 15 }
2.2.3 查找功能(与string的获取功能类似)
- char charAt(index)————查找某个位置上的字符
- int indexOf(String str)————获取子字符串在字符串中第一次出现的位置
- int lastIndexOf(String str)————获取子字符串在字符串中最后一次出现的位置
实践见真知
1 public class StringBufferDemo { 2 public static void main(String[] args) { 3 Demo_3(); 4 } 5 public static void Demo_3() { 6 StringBuffer sb = new StringBuffer(); 7 sb.append("abcdefg"); 8 char ch = sb.charAt(3);//返回字符串上某个位置的元素 9 System.out.println(ch);//d 10 11 int i = sb.indexOf("cde");//返回子串在主串上的位置 12 System.out.println(i);//2 13 14 int j = sb.lastIndexOf("de"); 15 System.out.println(j);//3 16 17 int x = sb.indexOf("ef", 3);//从指定位置上查找子串所在位置 18 System.out.println(x);//4 19 } 20 }
2.2.4 修改功能
- StringBuffer replace( start, end, string)————替换字符串,包含开头,不包含结尾
- void setCharAt(index,char)————在指定位置上插入某个字符
实践见真知
1 public class StringBufferDemo { 2 public static void main(String[] args) { 3 Demo_4(); 4 } 5 public static void Demo_4() { 6 StringBuffer sb = new StringBuffer(); 7 sb.append("abcdefg"); 8 sb.replace(1, 4, "123");//包含开头元素,不包含结尾 9 System.out.println(sb);//a123efg 10 // sb.replace(0, sb.length(), "");//这就相当于清空缓冲区 11 // System.out.println(sb.length());//0 12 13 sb.setCharAt(5, 'x');//在指定位置上插入某个字符 14 System.out.println(sb);//a123exg 15 } 16 }
2.2.5 额外功能
- void setLength(int newlength)————设置字符串缓冲区的长度,当长度设置为0时,相当于清空缓冲区
- StringBuffer reverse()————将此字符序列用其反转形式取代
实践见真知
1 public class StringBufferDemo { 2 public static void main(String[] args) { 3 Demo_5(); 4 } 5 public static void Demo_5() { 6 StringBuffer sb = new StringBuffer(); 7 sb.append("abcdefg"); 8 //字符串反转 9 sb.reverse(); 10 System.out.println(sb);//gfedcba 11 //设置字符串长度,当设置为0时,相当于清空缓冲区 12 sb.setLength(0); 13 System.out.println(sb.length());//0 14 } 15 }
2.2.6 构造方法StringBuffer()与StringBuffer(int capacity)的区别
StringBuffer()构造方法,是构造一个不带字符串的字符串缓冲区,初始容量为16个字符。当超过该容量时,可继续增加容量。而StringBuffer(int capacity)是构造一个固定长度的字符串缓冲区,但是当超过该固定容量时,依然可以继续扩展容量。二者的区别在于效率方面。当已知自己有35个字符的数据时,直接创建StringBuffer(40),效率更高。否则如果使用StringBuffer()创建,当发现容量不足时,还要继续创建,将会降低效率。
2.2.7 StringBuilder
从jdk1.5才开始出现StringBuilder,不保证同步,线程不安全,但是效率高,单线程时优先考虑使用StringBuilder
(三). StringBuffer与StringBuilder的区别
相同点:两者功能相同,使用方法相同
不同点:jdk1.0开始出现StringBuffer,线程安全,同步,多用于多线程
jdk1.5以后出现了和StringBuffer功能一样的StringBuilder,不保证同步,线程不安全,但是效率高,通常用于单线程
StringBuilder的出现是为了解决StringBuffer在处理单线程时效率慢问题,提高缓冲区的效率而出现的。
对比数组与StringBuffer或StringBuilder缓冲区:
1 public class StingBuilderDemo { 2 /** 3 * 需求:将一个int数组变成字符串 ,分别用数组、缓冲区方式 输出 4 * 对比使用数组与使用缓冲区的区别 5 * @param args 6 */ 7 public static void main(String[] args) { 8 int[] arr = {2,5,8,33,23,6}; 9 // ShowArr(arr); 10 String s = StringBuilderDemo(arr); 11 System.out.println(s); 12 } 13 //使用缓冲区方式 14 public static String StringBuilderDemo(int[] arr) { 15 StringBuilder sb = new StringBuilder(); 16 System.out.print("{"); 17 for (int i = 0; i < arr.length; i++) { 18 if(i!=arr.length-1){ 19 sb.append(arr[i]+","); 20 }else{ 21 sb.append(arr[i]+"}"); 22 } 23 } 24 return sb.toString(); 25 } 26 27 //使用数组方式 28 public static void ShowArr(int[] arr) { 29 System.out.print("{"); 30 for (int i = 0; i < arr.length; i++) { 31 if(i!=arr.length-1){ 32 System.out.print(arr[i]+","); 33 }else{ 34 System.out.println(arr[i]+"}"); 35 } 36 } 37 } 38 39
结论:使用数组方式输出时,每遍历一次,连接一次“,” 如:( System.out.print(arr[i]+",");)就会在字符串常量池中产生一个常量,当全部输出字符串时会在常量池中产生n多个常量。而使用StringBuffer或StringBuilder的方式,不断的往数组中装,最后只返回一个字符串。
(四). 实践见真知
实践一
1 package com.itsuper.p3.String; 2 3 public class Practice1 { 4 5 /** 6 * 将字符串数组按照字典顺序进行排序 7 * "nba","abc","cba","zz","qq","haha" 8 * @param args 9 */ 10 public static void main(String[] args) { 11 String[] arr = {"nba","abc","cba","zz","qq","haha"}; 12 printArray(arr); 13 sortArray(arr); 14 printArray(arr); 15 } 16 17 public static void sortArray(String[] arr) { 18 for (int i = 0; i < arr.length-1; i++) { 19 for (int j = i+1; j < arr.length; j++) { 20 if((arr[i].compareTo(arr[j])>0)){ 21 swap(arr,i,j); 22 } 23 } 24 } 25 } 26 //交换功能 27 private static void swap(String[] arr, int i, int j) { 28 String temp = arr[j]; 29 arr[j] = arr[i]; 30 arr[i] = temp; 31 } 32 33 //打印功能 34 public static void printArray(String[] arr) { 35 for(int i=0;i<arr.length;i++){ 36 if(i!=arr.length-1){ 37 System.out.print(arr[i]+","); 38 }else{ 39 System.out.println(arr[i]); 40 } 41 } 42 43 } 44 45 }
实践二
1 package com.itsuper.p3.String; 2 3 public class Practice2 { 4 5 /** 6 * 查找子串nba在字符串中出现的次数 7 * asnbadfjanbaljdgnbasjgljljnbassdfa 8 * @param args 9 * @return 10 */ 11 12 public static void main(String[] args) { 13 /* 14 * 分析: 15 * 次数:计数器 16 * 找nba,得有包含contains,先判断是否有nba,如果有则继续,如果没有则为0 17 * 首先找到nba出现位置,找到后计数1次;然后取剩余的子串,在找nba出现的位置,在计数一次;再取剩余子串,依次类推 18 * 得用到循环 19 */ 20 String str = "asnbadfjaljdgnbasjgljljnbassdfa"; 21 String key = "nba"; 22 int count = getStringKeyCount(str,key); 23 System.out.println("key-count:" + count ); 24 } 25 26 public static int getStringKeyCount(String str, String key) { 27 int count = 0; 28 if(!str.contains(key)){ 29 System.out.println("nba出现次数:"+count); 30 }else{ 31 while(str.contains(key)){ 32 //首先索引到第一次nba出现位置 33 int first = str.indexOf(key);//2 34 count++; 35 //找到下一次nba出现的位置 36 str = str.substring(first+key.length()); 37 System.out.println(str); 38 } 39 // System.out.println("key出现次数:"+count); 40 } 41 return count; 42 } 43 44 }
实践三
1 package com.itsuper.p3.String; 2 3 public class Pratice3 { 4 5 /** 6 * 判断两个字符串中的最大相同子串。 abcefgkvcdejflsndlssdf、mendkgkvcdejfieksel 7 * 8 * @param args 9 */ 10 11 /* 12 * 分析: 先拿短的字符串去看大串中是否包含,如果含有,则最大相同子串就是短的字符串 13 * 如果不含有,就将子串一次递减的方式,去放到长传中去看是否包含,知道找到最大子串 14 * 15 * 需要用到for循环 16 */ 17 public static void main(String[] args) { 18 String str1 = "abcefgkvcdejflsndlssdfdfa"; 19 String str2 = "mendkgkvcdejfieksel"; 20 String maxSubstr = FoundMaxSubstring(str1, str2); 21 System.out.println("最大相同子串:" + maxSubstr); 22 23 } 24 25 public static String FoundMaxSubstring(String str1, String str2) { 26 //如何知道str1、str2哪一个是大的串,哪一个是小的串呢?需要判断 27 String max = null; 28 String min = null; 29 max = (str1.length()>str2.length())?str1:str2; 30 min = (max.equals(str1))?str2:str1; 31 System.out.println("max="+max); 32 System.out.println("min="+min); 33 //两层for循环很值得好好研究 34 for (int x = 0; x < str2.length(); x++) { 35 for (int y = 0, z = str2.length() - x; z != str2.length() + 1; y++, z++) { 36 String sub = str2.substring(y, z); 37 if (str1.contains(sub)) 38 return sub; 39 } 40 } 41 // 如果没有,直接返回空 42 return null; 43 } 44 45 }
实践四
1 package com.itsuper.p3.String; 2 3 public class Practive4 { 4 5 /** 6 * 模拟trim功能一致的方法 7 * 实际是去除字符串两端的空白 8 * @param args 9 */ 10 public static void main(String[] args) { 11 String str = " abc dmef mdk "; 12 str = myTrim(str); 13 System.out.println("去除空格后的字符串:" + "--" + str + "---"); 14 } 15 public static String myTrim(String str) { 16 int startIndex = 0; 17 int endIndex = str.length()-1; 18 //判断是否是字符,反过来就是判断是否是空格,从头开始判断 19 while(startIndex < endIndex && (str.charAt(startIndex)) == ' ' ){ 20 startIndex++; 21 } 22 while(startIndex < endIndex && (str.charAt(endIndex)) == ' '){ 23 endIndex--; 24 } 25 str = str.substring(startIndex, endIndex); 26 return str; 27 } 28 29 }