------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
第一部分、String、StringBuffer、StringBuilder
一、String类
1、概述
String类型的特点:字符串对象一旦被初始化就不会被改变。
String s=“abc”;s=“nba”;
"abc"字符串对象并没有被改变,只是引用变量s指向了新创建的字符串对象"nba"。
Java中String是一个特殊的包装类数据有两种创建形式:
- String s1 = "abc";
- String s2 = new String("abc");
第一种先在栈中创建一个对String类的对象引用变量s,然后去查找"abc"是否被保存在字符串常量池中,如果没有则在栈中创建三个char型的值'a'、'b'、'c',然后在堆中创建一个String对象object,它的值是刚才在栈中创建的三个char型值组成的数组{'a'、'b'、'c'},接着这个String对象object被存放进字符串常量池,最后将s指向这个对象的地址,如果"abc"已经被保存在字符串常量池中,则在字符串常量池中找到值为"abc"的对象object,然后将s指向这个对象的地址。
第一种特点:JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。
第二种可以分解成两步1、String object = "abc"; 2、String s = new String(object); 第一步参考第一种创建方式,而第二步由于"abc"已经被创建并保存到字符串常量池中,因此jvm只会在堆中新创建一个String对象,它的值共享栈中已有的三个char型值。
第二种特点:一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象。所以这里的s1!=s2。
String类复写了Object中的equals方法,建立了String类自己的判断字符串对象是否相同的依据。只比较字符串内容,不比较地址。所以s1.equals(s2)为真。
2、构造函数
第一类:public String(byte[] bytes) 通过字节数组构造一个字符串对象。
第二类:public String(char[] value) 通过字符数组构造一个字符串对象。
详细的构造函数可以参考API的说明:
3、String类常见方法介绍
第一类获取:
int length();获取字符串中字符的个数(长度)
char charAt(int index);根据位置获取字符
int indexOf(int ch);根据字符获取在字符串中的位置。indexO方法参数f类型为int是为了既可以支持字符,也可以支持字符在ASCII码中对应的数字。
int indexOf(int ch,int fromIndex);从指定位置开始查找ch第一次出现的位置。
int lastIndexOf(int ch);根据字符串获取在字符串中第一次出现的位置。找不到返回-1.
String substring(int beginIndex,int endIndex);获取字符串中的一部分字符串,也叫子串。
String substring(int beginIndex);
第二类转换:
String[] split(String regex);将字符串变成字符串数组(字符串的切割)涉及到正则表达式。
char[] toCharArray();将字符串变成字符数组。
char[] getBytes();将字符串变成字节数组
String toUpperCase();大写
String toLowerCase();小写
String replace(char oldCh,char newCh);将字符串中的内容进行替换,replace方法如果没有找到要替换的内容,则返回的还是原字符串。
String replace(String s1,String s2);
String trim();去除字符串两端空格
String concat(String str);将字符串进行连接。concat效果与"+"连接符效果一致,但是效果更高一些。
第三类判断
boolean equals(Object obj);两个字符串内容是否相同
boolean equalsIgnoreCase(String str);忽略大小写比较字符串内容。
boolean contains(String str);字符串中是否包含指定字符串
boolean startsWith(String str);字符串是否以指定字符串开头
boolean endsWith(String str);是否以指定字符串结尾
第四类比较
int compareTo(String str); 如果参数字符串等于此字符串,则返回值0;如果此字符串按字典顺序小于字符串参数,则返回一个小于0的值;如果此字符串按字典顺序大于字符串参数,则返回一个大于0的值
String intern();返回字符串对象的规范化表示形式,当调用intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。
学了这么多的String类型的方法,下面用几个个综合应用来练习一下这些方法。
练习1、
1 /* 2 1、对字符串"12 5 42 32 87 -7 55 7 8"中的数字进行排序。 3 思路: 4 第一步将字符串转换成为字符串数组 5 第二步将字符串数组转换成为整数数组 6 第三步对整数数组排序, 7 第四部把排序后的整数数组转换成为字符串 8 */ 9 import java.util.*; 10 class StringSort 11 { 12 public static void main(String[] args) 13 { 14 String strSrc="12 5 42 32 87 -7 55 7 8"; 15 //1、将字符串转换成为字符串数组 16 String[] strs = strToCharArray(strSrc); 17 //第二步将字符串数组转换成为整数数组,split方法 18 int[] strInts =strsToInts(strs); 19 //整数数组排序 20 mySort(strInts); 21 22 sop("排序前字符串为:"+strSrc); 23 //把排序后的整数数组转换成为字符串 24 sop("排序前字符串为:"+intsToString(strInts)); 25 } 26 public static void sop(Object obj) 27 { 28 System.out.println(obj); 29 } 30 31 static String[] strToCharArray(String str) 32 { 33 return str.split(" "); 34 } 35 36 static int[] strsToInts(String[] strs) 37 { 38 int[] ints=new int[strs.length]; 39 for(int i=0;i<strs.length;i++) 40 { 41 ints[i]=Integer.parseInt(strs[i]); 42 } 43 return ints; 44 } 45 //排序 46 static void mySort(int[] ints) 47 { 48 for(int i=0;i<ints.length-1;i++) 49 { 50 for(int j=i+1;j<ints.length;j++) 51 { 52 if(ints[i]>ints[j]) 53 { 54 int temp=ints[i]; 55 ints[i]=ints[j]; 56 ints[j]=temp; 57 } 58 } 59 } 60 } 61 62 static String intsToString(int[] ints) 63 { 64 StringBuilder str=new StringBuilder(); 65 for(int i=0;i<ints.length;i++) 66 { 67 if(i!=ints.length-1) 68 str.append(ints[i]+" "); 69 else 70 str.append(ints[i]); 71 } 72 return str.toString(); 73 } 74 }
结果为:
练习2:
1 /* 2 2、一个子串nba在整串中出现的次数 "nbaernbatynbauinbaopnba" 3 思路:indexOf获取子串在字符串中的位置,如果大于0则说明存在,小于0则说明不存在。 4 如果找到了,就在找到的位置加上子串的长度位置开始查找,知道小于0. 5 */ 6 public static void Excercise02() 7 { 8 String src = "nbaernbatynbauinbaopnba"; 9 String key = "nba"; 10 int count = getKeyCount(src,key); 11 System.out.println("count: "+count); 12 } 13 public static int getKeyCount(String src,String key) 14 { 15 int count=0; 16 int fromIndex=0; 17 while((fromIndex=src.indexOf(key,fromIndex))!=-1) 18 { 19 fromIndex=fromIndex+key.length();//将查找的起始位置偏移继续查找 20 count++; 21 } 22 return count; 23 }
结果为:
可以看到nba在目的串中确实是出现了五次。
练习3、
1 3、两个字符串中最大相同的子串 2 "qwerabcdtyuiop" 3 "xcabcdvbn" 4 思路: 5 ①既然取的是最大子串,先看短的那个字符串是否在长的那个字符串中。如果存在,短的那个字符串 6 就是最大子串。 7 ②如果不是,那么就将短的那个子串进行长度递减的方式去子串,去子串中判断是否存在。如果存在 8 就已找到,就不用再找了 9 */ 10 public static void excercise03() 11 { 12 String s1="qwerabcdtyuiop"; 13 String s2="xcabcdvbn"; 14 String s=getMaxSub(s1,s2); 15 System.out.println(s1+","+s2+"的最大共同子串为: "+s); 16 } 17 public static String getMaxSub(String s1,String s2) 18 { 19 String max=null,min=null; 20 max=s1.length()>s2.length()?s1:s2; 21 min=max.equals(s1)?s2:s1;//找出两个字符串哪个长,哪个短 22 for(int i=0;i<min.length();i++) 23 { 24 for(int a=0,b=min.length()-i-1;b<min.length();a++,b++) 25 { 26 String temp=min.substring(a,b+1);//sub方法包含头不包含尾 27 if(max.contains(temp)) 28 { 29 return temp; 30 } 31 } 32 } 33 return null; 34 35 }
运行结果为:
最长的共同子串确实为abcd。
StringBuffer
StringBuffer:就是字符串缓冲区,用于存储数据的容器。
StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。
在StringBuffer类中存在很多和String类一样的方法,这些方法在功能上和String类中的功能是完全一样的。但是有一个最显著的区别在于,对于StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。
StringBuffer的特点:长度可变,可以存储不同类型的数据。最终要转换成为字符串进行使用。StringBuffer的字符串缓冲区初始容量为16个字符,其实质还是数组。
StringBuffer类的方法介绍:
添加:
StringBuffer append(data);在末尾添加
StringBuffer insert(index,data);在指定位置添加,insert方法也可以对字符串进行修改。
删除:
StringBuffer delete(int start,int end);包含头,不包含尾。
StringBuffer deleteCharAt(int index):删除指定位置的元素
特有方法:
void setLength(int newLength);设置字符序列的长度
public StringBuffer reverse();将字符序列用其反转形式取代
注意:使用setLength设置StringBuffer中字符序列的长度。如果小于已有字符序列的长度,相当于清除缓冲区中的一部分内容。如果大于已有字符序列的长度,相当于扩充缓冲区,扩充部门内容用空格字符填充。
当创建的StringBuffer内容长度大于16,将会新创建一个新数组,长度比旧数组要长。然后把就数组的内容拷贝到新的数组,超出旧数组长度范围的内容将会放在新数组现在内容的后面,也可以通过StringBuffer(int capacity);构造函数自己设置StringBuffer缓冲区长度。
StringBuilder
jdk1.5以后出现了功能和StringBuffer一模一样的对象,就是StringBuilder。
StringBuffer和StringBuilder两者的区别:
StringBuffer是线程同步的,通常用于多线程。StringBuilder是线程不同步的,通常用于单线程,它的出现能够提高程序效率。故StringBuilder多用于多个线程是不安全的,如果需要这样的同步,可以使用StringBuffer或者自己用加同步锁。
小知识:JDK升级的目的:简化书写,提高效率,增加安全性。
接下来用StringBuilder做一个小练习:将一个整数数组转化为一个字符串。
1 /* 2 4、将一个整数数组转化为一个字符串 3 */ 4 public static String exercise04() 5 { 6 int[] its={1,2,3,4,5,6,7,10}; 7 StringBuilder sb=new StringBuilder();//StringBuilder避免了String反复创建对象,提高了效率 8 for(int i=0;i<its.length;i++) 9 { 10 if(i!=its.length-1) 11 { 12 sb.append(its[i]+",");//在数字中间加逗号分隔 13 } 14 else 15 sb.append(its[i]);//最后一个数不加逗号 16 } 17 return sb.toString(); 18 }
运行的结果为:
第二部分、基本数据包装类
为了方便操作基本数据类型值,将其封装成了对象,在对象中定义了属性和行为丰富了该数据的操作。用于描述该对象的类就称为基本数据类型对象包装类。
基本数据类型------》基本数据包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
该包装对象主要用于基本类型和字符串之间的转换:
基本类型--》字符串
1. 基本类型数值+""
2. 用String类中的静态方法valueOf(基本类型数值);
字符串--》基本数据类型
1. 使用包装类中的静态方法xxx parseXxx("xxx");如:int parseInt(String str);
2. 如果字符串被Integer进行对象的封装,可使用另一个非静态的方法,intValue。将一个Integer对象转成基本数据类型值。
3. 用Integer的静态方法valueOf(String s);
进制转换:
十进制-->其他进制方法:String toBinaryString(int i);等
其他进制-->十进制方法:int parseInt(String s,int radix);
1 public static void exercise05() 2 { 3 System.out.println(Integer.parseInt("123")); 4 System.out.println(Integer.valueOf("123")); 5 //十进制--》其它进制 6 System.out.println(Integer.toBinaryString(60)); 7 System.out.println(Integer.toOctalString(60)); 8 System.out.println(Integer.toHexString(60)); 9 System.out.println(Integer.toString(60,2)); 10 //其他进制--》十进制 11 System.out.println(Integer.parseInt("110",16)); 12 System.out.println(Integer.parseInt("110",10)); 13 System.out.println(Integer.parseInt("110",8)); 14 System.out.println(Integer.parseInt("110",2)); 15 }
运行结果为:
本次内容总结到这里就完了,字符串这个特殊的类对象,需要非常熟悉类中的各种方法,在编程时就能显著的提高程序的运行效率。内容上字符串的特性需要从原理上理解,更多的是需要记忆和练习String类中的各种方法。