一直以为String、Array、Collection、File、I-O是所有编程语言的基础也是重点。
今天简单对String做以简单的小结。
《编程思想》中的开场语:可以证明,字符串操作是计算机程序设计中最常见的行为。尤其是在java大展拳脚的Web系统中。
Java中String的几个要点:
1.String是不可变的
2.String的基本操作
3.StringBuffer & StringBuilder
进击的String:
1.格式化的输出
2.正则表达式
3.扫描输入
1.不可变的String
根据JDK的描述,我们可以看到String类型在从创建之后就是不可变的,只能shared,不能change.
《thinking In java》按:String类中任何看来会修改String值的方法,实际都是创建了一个全新的String对象,以包含修改后的字符串内容。而最初的String对象丝毫未动。
// String abc = "abc"; 两种
char[] data = {'a', 'b', 'c'};
String abc = new String(data);
System.out.println(abc.toUpperCase()); //ABC
System.out.println(abc); //abc
上面可以看到虽然对abc做了upperCase,但是abc本身并没有做出任何变化。实际上abc.toUpperCase只是返回了一个新的String对象。
2.String类的基本操作
package test;
public class TestString {
public static void main(String[] args) {
String test = new String("hello WORLD! ");
String replace = test.replace('o', 'a');
String upperCase = test.toUpperCase();
System.out.println(upperCase);//HELLO WORLD!
String lowerCase = test.toLowerCase();//hello world!
System.out.println(lowerCase);
char index = test.charAt(3);
System.out.println(index);//l
int codePoint = test.codePointAt(3);
System.out.println(codePoint);//108
//compareToIgnoreCase
System.out.println(test.compareToIgnoreCase(lowerCase));//0
System.out.println(test.compareToIgnoreCase(upperCase));//0
System.out.println(upperCase.compareToIgnoreCase(lowerCase));//0
//compareTo
System.out.println(upperCase.compareTo(lowerCase));//-32
//concat
System.out.println(lowerCase.concat(upperCase));//hello world! HELLO WORLD!
//substring
System.out.println(test.substring(2));//llo WORLD!
System.out.println(test.substring(0, 5));//hello
//trim
System.out.println(test.trim());//hello WORLD!注意这里的空格被去掉了
System.out.println(test);//hello WORLD! 最后一个有空格,test从没改变
}
}
3.StringBuffer & StringBuilder
JDK中给出的StringBuffer的解释:
String buffers are safe for use by multiple threads.
The principal operations on a StringBuffer are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string buffer.
简单解释一下:
StringBuffer最主要的操作是 append和 insert接口,这些接口都已经被重写过以便支持各种数据类型。这些方法首先将给定数据转换成String类型,然后再将该string对象appends 或者insert到stringbuffer对象中。事实上,sb.append(x)的效果与sb.insert(sb.length(),x)是一样的。
简单测试一下:
StringBuffer buffer = new StringBuffer("hello world! ");
buffer.append("I am me! ");
System.out.println(buffer);//hello world! I am me!
buffer.insert(5, " my");
System.out.println(buffer);//hello my world! I am me!
可以看粗,StringBuffer的确是像一个String,但是可以修改。
有意思的是JDK文档中给出的最后一段话
上文中提到StringBuffer是有容积的。只要string buffer 中的字符序列不超过buffer的容积,就不会再分配新的array给它,否则溢出的话,会自动扩展。JDK5提供了stringbuffer的一个单线程等价类——StringBuilder。同时JDK建议,应该优先考虑StringBuilder,因为它的接口与StringBuffer完全一样,但是要更快,不过是非线程安全的。
再看StringBuilder:
JDK给的定义:
与上面的StringBuffer后面给出的对比如出一辙,可笑的是,后面的关于接口功能的介绍貌似是从StringBuffer文档中直接copy过来的,由此可见,StringBuilder实际上是单线程情况下高效版StringBuffer,功能几乎完全一样。
来个小结:
String类不可变,在每次对String对象做改变操作的时候总是会生成新的String对象,如果程序中有频繁的改动字符串内容的操作,那么势必会在内存中产生许多无引用对象,导致GC,拖慢速度。
在上面StringBuffer的JDK文档中也说的很明白,StringBuffer最主要的操作就是append,insert等改变string内容的接口,因此如果需要频繁的修改String内容的话,推荐使用StringBuffer(多线程)、StringBuilder(单线程)。