Java的String&StringBuffer&StringBuilder
一:String类
1.String对象的初始化
由于String对象特别用,所以在对String对象进行初始化时,Java提供了一种简化的特殊语法,格式如下:
String s = "abc"; s = "Java语言";
其实按照面向对象的标准语法,其格式应该为:
String s = new String("abc"); s =new String("Java语言");
只是按照面向对象的标准语法,在内存使用上存在比较大的浪费。如String s = new String(“abc”);实际上创建了两个String对象,一个是”abc”对象,存储在常量空间中,一个是使用new关键字为对象s申请的空间。
2.字符串的常见操作方法
2.1.charAt方法
该方法的作用是按照索引值(规定字符串中第一个字符串的索引值是0,第二个索引值是1,依次类推)获得字符串中指定的字符。例如:
String s = "abc"; char c = s.charAt(1); 则变量c的值是'b';
2.2.compareTo方法
该方法的作用是比较两个字符串的大小。比较的原理是依次比较每个字符的字符编码。首先比较的是两个字符串的第一个字符,如果第一个字符串的字符编码大于第二个字符串的字符编码,则返回大于0的值,如果小于则返回小于0的值,如果相等则比较后续的字符,如果两个字符串中的字符编码完全相同则返回0.
例如:
String s = "abc";
String s1 = "abd"; int value = s.compareTo(s1); 则value的值是小于0的值,即-1;
在String类中还存在一个类似的方法compareToIgnoreCase,这个方法是忽略大小写进行比较,比较的规则和compareTo一样。例如:
String s = "abc"; String s1 = "ABC"; int value = s.compareToIgnoreCase(); 则value的值为0,即连个字符串相等。
2.3.concat方法
该方法的作用是进行字符串的连接,将两个字符串连接以后形成一个新的字符串。例如:
String s = "abc";
String s1 = "def"; String s3 = s.concat(s1);
则连接以后生成的新字符串s2的值是”abcdef”,而字符串s和s1的值不发生改变。如果需要连接多个字符串,可以使用如下方法:
String s = "abc"; String s1 = "def"; String s2 = "1234"; String s3 = s.concat(s1).concat(s2);
则生成的新字符串s3的值为”abcdef1234”。
其实在实际使用时,语法上提供了一种更简单的形式,就是使用“+”进行字符串的连接。例如:
String s = “abc” + “1234”;
则字符串s的值是”abc1234”,这样书写更加简单直观。
而且使用“+”进行连接,不仅可以连接字符串,也可以连接其他类型。但是要求进行连接时至少有一个参与连接的内容是字符串类型。而且“+”匹配的顺序是从左向右,如果两边连接的内容都是基本数字类型则按照加法运算,如果参与连接的内容有一个是字符串才按照字符串进行连接。例如:
int a = 10; String s = "123"+a+5;
则连接以后字符串s的值是“123105”,计算的过程为首先连接字符串”123”和变量a的值,生成字符串”12310”,然后使用该字符串再和数字5进行连接生成最终的结果。
还有一个好处是,可以直接将部分其他类型直接转换成String类型。例如:
int a = 10; String b = a+"";
2.4.startsWith与endsWith方法
startsWith:该方法的作用和endsWith方法类似,只是该方法是判断字符串是否以某个字符串作为开始。例如:
String s = "TestGame"; boolean b = s.startsWith("Test"); 则变量的值是true。
endsWith:该方法的作用是判断字符串是否以某个字符串结尾,如以对应的字符串结尾,则返回true。例如:
String s = "student.doc"; boolean b = s.endsWith("doc"); 则变量的值是true。
2.5.equals方法
该方法的作用是判断两个字符串对象的内容是否相同。如果相同则返回true,否则返回false。例如:
String s = "abc"; String s1 = new String("abc"); boolean b = s.equals(s1); 结果返回 true。
而使用"=="比较的是两个对象在内存中存储的地址是否一样。例如上面的代码中,如果判断:
boolean b = (s==s1);
则变量b的值是false,因为s对象对应的地址是”abc”的地址,而s1使用new关键字申请新的内存,所以内存地址和s的”abc”的地址不一样,所以获得的值是false。
在String类中存在一个类似的方法equalsIgnoreCase,该方法的作用是忽略大小写比较两个字符串的内容是否相同。例如:
String s = "abc"; String s1 = "ABC"; boolean b = s.equalsIgnoreCase(s1);
则变量b的值是true。
2.6.getBytes方法
该方法的作用是将字符串转换为对应的byte数组,从而便于数据的存储和传输。例如:
String s = "计算机";
byte[] b = s.getBytes();//使用本机默认的字符集转换为byte数组
byte[] b = s.getBytes("gb2312");//使用gb2312字符集转换byte数组
2.7.indexOf方法
该方法的作用是查找特定字符或字符串在当前字符串中的其实位置,如果不存在则返回-1。例如:
String s = "abcded";
int index = s.indexOf('d');
int index1 = s.indexOf("hf");
则返回字符d在字符串s中第一次出现的位置,数值为3。由于字符串hf在字符串三种不存在,则index1的值是-1。
2.8.length方法
该方法的作用是返回字符串的长度,也就是返回字符串中字符的个数。中文字符也是一个字符。例如:
String s = "abc"; String s1 = "Java语言"; int len = s.length(); int len2 = s1.length();
则变量len的值是3;变量len1的值是6;
2.9.replace方法
该方法的作用是替换字符串中所指定的字符,然后生成一个新的字符串。经过该方法调用以后,原来的字符串不发生改变。例如:
String s = "abcat"; String s1 = s.replace('a','1');
该代码的作用是将字符串s中所有的字符a替换成字符1,生成的新字符串s1的值是”1bc1t”,而字符串s的内容不发生改变。
如果需要将字符串中某个指定的字符串替换为其它字符串,则可以使用replaceAll方法,例如:
String s = "abatbac"; String s1 = s.replaceAll("ba","12");
该代码的作用是将字符串s中所有的字符串”ab”替换为”12”,生成新的字符串”a12t12c”,而字符串s的内容也不发生改变。
如果只需要替换第一个出现的指定字符串时,可以使用replaceFirst方法,例如:
String s = "abatbac"; String s1 = s.replaceFirst ("ba","12");
该代码的作用是只将字符串s中第一次出现的字符串”ab”替换为字符串”12”,则字符串s1的值是”a12tbac”,字符串s的内容也不发生改变。
2.10.split方法
该方法的作用是以特定的字符串作为间隔,拆分当前字符串的内容,一般拆分以后会获得一个字符串数组。例如:
String s = "ab,12,df"; String[] s1 = s.split(",");
该代码的作用是以字符串”,”作为间隔,拆分字符串s,从而得到拆分以后的字符串数组s1,其内容为:["ab","12","df"]。该方法是解析字符串的基础方法。
2.11.substring方法
该方法的作用是取字符串中的“子串”。例如:
String s = "Test"; String s1 = s.substring(2);
则该代码的作用是取字符串s中索引值为2(包括)以后的所有字符作为子串,则字符串s1的值是”st”。
如果数字的值和字符串的长度相同,则返回空字符串。例如:
String s = "Test"; String s1 = s.substring(4); 则字符串s1的值是""。
如果需要取字符串内部的一部分,则可以使用带2个参数的substring方法,例如:
String s = "TestString"; String s1 = s.substring(2,5);
则该代码的作用是取字符串s中从索引值2(包括)开始,到索引值5(不包括)的部分作为子串,则字符串s1的值是"stS"。
2.12.toCharArray方法
该方法的作用和getBytes方法类似,即将字符串转换为对应的char数组。例如:
String s = "abc"; char[] c = s.toCharArray(); 则字符数组c的值为:['a','b','c']。
2.13.toLowerCase方法
该方法的作用是将字符串中所有大写字符都转换为小写。例如:
String s = "AbC123"; String s1 = s.toLowerCase(); 则字符串s1的值是”abc123”,而字符串s的值不变。
类似的方法是toUpperCase,该方法的作用是将字符串中的小写字符转换为对应的大写字符。例如:
String s = "AbC123"; String s1 = s. toUpperCase (); 则字符串s1的值是”ABC123”,而字符串s的值也不变。
2.14.trim方法
该方法的作用是去掉字符串开始和结尾的所有空格,然后形成一个新的字符串。该方法不去掉字符串中间的空格。例如:
String s = " abc abc 123"; String s1 = s.trim(); 则字符串s1的值为:” abc abc 123”。字符串s的值不变。
2.15.valueOf方法
该方法的作用是将其他类型的数据转换成字符串类型。需要注意的是,基本数据和字符串对象之间不能使用以前的强制类型转换的语法进行转换。另外由于该方法是static的方法,所以不用创建String类型的对象即可。例如
int n = 10; String s = String.valueof(10); 则字符串s的值是”10”。虽然对于程序员来说,没有发生什么变化,但是对于程序来说,数据的类型却发生了变化。
介绍一个简单的应用,判断一个自然数是几位数字的逻辑代码如下:
int n = 12345; String s = String.valueOf(n); int len = s.length();
则这里字符串的长度len,就代表该自然数的位数。这种判断比数学判断方法在逻辑上要简单一些。
关于String类的使用就介绍这么多,其它的方法以及这里到的方法的详细声明可以参看对应的API文档。
====================================================================================================================================================================================================================================================================================
二:StringBuffer类
StringBuffer类和String一样,也用来代表字符串,只是StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。所以在实际使用的时候,如果经常需要对一个字符串进行修改,例如插入,删除等操作,使用StringBuffer要更加适合一些。
在StringBuffer类中存在很多和String类一样的方法,这些方法在功能上和String类中的功能是完全一样的。但是有一个最显著的区别在于,对于StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。
另外由于StringBuffer是线程安全的,所以在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些。
1.StringBuffer对象的出初始化不像String类的初始化一样,java提供的有特殊的语法,而通常情况下一般使用构造方法进行初始化。
例如:StringBuffer s = new StringBuffer();
这样初始化出的Stringbuffer对象是一个空的对象。如果需要创建带有内容的StringBuffer对象,则可以使用:
StringBuffer s = new StringBuffer("abc");
这样初始化出的StringBuffer对象的内容就是字符串"abc"。
需要注意的是,StringBuffer和String属于不同的类型,也不能直接进行强制类型转换,下面的代码都是错误的:
StringBuffer s = "abc"; //赋值类型不匹配
StringBuffer s = (StringBuffer)"abc"; //不存在继承关系,无法进行强转
StringBuffer对象和String对象之间的互转的代码如下:
String s = "abc";
StringBuffer sb1 = new StringBuffer("123");
StringBuffer sb2 = new StringBuffer(s); //将String转换为StringBuffer
String s1 = sb1.toString(); //将StringBuffer转换为String
2.StringBuffer的常用方法
StringBuffer类中的方法主要偏重于对字符串的变化,例如追加,插入和删除等,这个也是StringBuffer和String类的主要区别。
2.1.append方法
该方法的作用是追加内容到当前StringBuffer对象的末尾,类似于字符串的连接。调用该方法以后,StringBuffer对象的内容也发生改变,例如:
StringBuffer sb = new StringBuffer("abc"); sb.append(true); 则对象sb的值将变成”abctrue”。
使用该方法进行字符串的连接,将比String更加节约内容,例如应用于数据库SQL语句的连接,例如:
StringBuffer sb = new StringBuffer(); String user = "test"; String pwd = "123";
sb.append("select * from userInfo where username=").append(user).append("and pwd=").append(pwd);
这样对象sb的值就是字符串"select * from userInfo where username=test and pwd=123"。
2.2.deleteCharAt方法
该方法的作用是删除指定位置的字符,然后将剩余的内容形成新的字符串。例如:
StringBuffer sb = new StringBuffer("Test");
sb. deleteCharAt(1);
该代码的作用删除字符串对象sb中索引值为1的字符,也就是删除第二个字符,剩余的内容组成一个新的字符串。所以对象sb的值变为”Tst”。
还存在一个功能类似的delete方法: public StringBuffer delete(int start,int end)
该方法的作用是删除指定区间以内的所有字符,包含start,不包含end索引值的区间。例如:
StringBuffer sb = new StringBuffer("TestString"); sb. delete (1,4);
该代码的作用是删除索引值1(包括)到索引值4(不包括)之间的所有字符,剩余的字符形成新的字符串。则对象sb的值是"TString"。
2.3.insert方法
该方法的作用是在StringBuffer对象中插入内容,然后形成新的字符串。例如:
StringBuffer sb = new StringBuffer("TestString"); sb.insert(4,false);
该示例代码的作用是在对象sb的索引值4的位置插入false值,形成新的字符串,则执行以后对象sb的值是"TestfalseString"。
2.4.reverse方法
该方法的作用是将StringBuffer对象中的内容反转,然后形成新的字符串。例如:
StringBuffer sb = new StringBuffer("abc"); sb.reverse(); 经过反转以后,对象sb中的内容将变为"cba"。
2.5.setCharAt方法
public void setCharAt(int index, char ch)
该方法的作用是修改对象中索引值为index位置的字符为新的字符ch。例如:
StringBuffer sb = new StringBuffer("abc");
sb.setCharAt(1,'D');
2.6.trimToSize方法
public void trimToSize()
该方法的作用是将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度,减少空间的浪费。
总之,在实际使用时,String和StringBuffer各有优势和不足,可以根据具体的使用环境,选择对应的类型进行使用。
====================================================================================================================================================================================================================================================================================
三:StringBuilder类
相信大家看到过很多比较String和StringBuffer区别的文章,也明白这两者的区别,然而自从Java 5.0发布以后,我们的比较列表上将多出一个对象了,这就是StringBuilder类。String类是不可变类,任何对String的改变都会引发新的String对象的生成;而StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象,可变和不可变类这一对对象已经齐全了,那么为什么还要引入新的StringBuilder类干吗?相信大家都有此疑问,我也如此。下面,我们就来看看引入该类的原因。
原因在于当改变字符串内容时,采用StringBuffer能获得更好的性能。既然是为了获得更好的性能,那么采用StringBuffer能够获得最好的性能吗?答案是NO!
如果你读过《Think in Java》,而且对里面描述HashTable和HashMap区别的那部分章节比较熟悉的话,你一定也明白了原因所在。对,就是支持线程同步保证线程安全而导致性能下降的问题。HashTable是线程安全的,很多方法都是synchronized方法,而HashMap不是线程安全的,但其在单线程程序中的性能比HashTable要高。StringBuffer和StringBuilder类的区别也在于此,新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。所以,如果我们的程序是在单线程下运行,或者不必考虑到线程同步问题,我们应该有限使用StringBuilder类。当然,如果要保证线程安全,自然非StringBuffer莫属了。其次,StringBuilder和Stringbuffer的方法使用上都是大同小异的。