3.6 字符串
Java字符串就是Unicode字符序列,Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类String(java.lang.String)。每个用双引号括起来的字符串(即java的字符串字面值)都是String类的一个实例,例如:
String e = “”;
String greeting=“hello”;
(1)提取子串
String类的substring方法可以从一个较大的字符串提取出一个子串,例如:
String greeting=“Hello”;
String s=greeting.substring(0,3);//s的值为“Hel”
|
|
|
|
substring方法的第一个参数是开始复制的第一个位置。
substring方法的第二个参数是不想复制的第一个位置,例如上例中要复制的位置是从0到2,不包含3。
substring的工作方式利于计算子串的长度,即字符串s.substring(a,b)的长度为b-a。
(2)字符串拼接
Java语言允许使用+号连接两个字符串,例如:
String s1="hel";
String s2="lo";
String s=s1+s2;
System.out.println(s); //输出hello
当将一个字符串与一个非字符串的值进行拼接时,后者会被转换成字符串(任何一个java对象都可以转换成字符串),例如:
int s1=13;
String s2=".jpg";
String s=s1+s2;
System.out.println(s); //输出13.jpg
这种特性也通常用在输出语句中,例如:
System.out.println(“The number is ”+num);//num可以是int型
(3)不可变字符串
和C/C++不同,String类没有提供用于修改字符串的方法,如果希望将String s=“Hello”的内容修改为“HelLO”,不能直接将s的最后两个位置修改为“L”和“O”。如果确实需要修改,只能首先提取需要的字符,然后再拼接上替换的字符串形成一个新的字符串实例,例如
String s="Hello";
s=s.substring(0,3)+"LO";
System.out.println(s);
由于不能修改java字符串中的字符,所以Java文档中将String类对象成为不可变字符串。不可变字符串虽然降低了字符串修改时的运行效率,但优点是:编译器可以让字符串共享。
具体的工作方式是:可以想象将各种字符串值存放在公共的存储池中,字符串变量指向存储池中相应的位置,如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符。
换言之,Java的设计者认为共享带来的高效率远远胜过提取 、拼接字符串所带来的低效率。
一般的程序很少需要修改字符串,更多地是进行字符串的比较,例外的情况就是将源自于文件或键盘的单个字符或较短的字符串汇集成字符串,为此Java提供了一个独立的类“构建字符串”。
|
(4)检测字符串是否相等
可以使用equals方法检测两个字符串是否相等,对于字符串s和t,利用以下表达式:
s.equals(t)
比较s和t,如果相等返回true,否则返回false。需要注意的是:s和t可以是字符串变量也可以是字符串常量。例如:“Hello”.equals(str)。
要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase方法。例如:
“Hello”.equalsIgnoreCase(”hello”)
特别注意:一定不能使用= =运算符检测两个字符串是否相等。这个运算符这能确定两个字符串是否放置在同一个位置上,而不是比较两个字符串的内容。
C++的string类重载了==运算符以便检测字符串内容的相等性,而Java没有采用这种方式,C程序员从不使用==对字符串进行比较,而使用strcmp函数。Java的compareTo方法与strcmp完全类似,它的声明如下:public int compareTo(String anotherString);例如if(str.compareTo(“Hello”) == 0)… 不过,使用equals更为清晰。 |
(5)代码点与代码单元
Java字符串由char序列组成,而字符数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元。大多数常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。
UTF-16使用16至21位二进制位表达,即从/u0000到 /u10FFFF。/u0000到/uFFFF表示基本的16位字符,/u10000到/u10FFFF表示辅助字符(supplymentary characters)。 辅助字符由一个高位替代符(high-surrogate )和一个低位替代符(low-surrogate )共同组成。高位替代符使用一个/uD800到/uDBFF之间的字符表示;低位替代符使用一个/uDC00到/uDFFF之间的字符表示。假设:A代表辅助字符(SC)的码点值; B代表SC的高位替代符的码点(Unicode code point)值; C代表SC的低位替代符的码点值。那么下面的等式成立:A = (B - 0xD800) << 10 + (C - 0xDC00) + 0x10000在将Unicode还原为可阅读字符的时候,当且仅当当前字符时高位替代符,下一字符是低位替代符时,此连续的两个字符被解释为辅助字符。 |
Java以独特的风格对字符串中的代码单元计数:字符串中的第一个代码单元位置为0,这种习惯起源于C。
length方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。例如:
String str=“Hello”;
int n=str.length();//is 5
要想得到实际的长度,即代码点数量,可以调用:
int cpCount=str.codePointCount( 0,str.length());
调用s.charAt(n)可返回位置n的代码单元,n介于0~s.length()-1之间,例如:
char first = str.charAt(0); //is ‘H’
char last = str.charAt(str.length()-1); // is ‘o’
(6)字符串API
Java的String类包含了50多个方法,并且绝大多数都很实用。下面汇总了一部分最常用的方法:
1)字符串比较
boolean equals(Object other) 检测字符串相等,如果字符串与other相等,返回true,否则返回false |
boolean equalsIgnoreCase(String other) 检测字符串相等(忽略大小写),如果相等返回true,否则返回false |
int compareTo(String other) 按照字典顺序如果字符串位于other之前返回负数;如果位于other之后返回正数;相同返回0; |
2)字符串匹配和判断
int length() 返回字符串的长度 |
char charAt(int index) 返回给定位置的代码单元,除非对底层的代码单元感兴趣,否则不需要调用这个方法。 |
boolean startsWith(String prefix) 如果字符串以prefix字符串开始,返回true |
boolean endsWith(String suffix) 如果字符串以suffix结尾返回true。 |
int indexOf(String str) int indexOf(String str,int fromIndex) int indexOf(int cp) int indexOf(int cp,int fromIndex) 返回与字符串str或代码点cp匹配的第一个子串的开始位置,这个位置从索引0或fromIndex开始计算,如果在原始串中不存在str,返回-1 |
int lastIndexOf(String str) int lastIndexOf(String str,int fromIndex) int lastIndexOf(int cp) int lastIndexOf(int cp,int fromIndex) 返回与字符串str或代码点cp匹配的最后一个子串的开始位置,这个位置从原始串尾端或fromIndex开始计算。 |
int codePointAt(int index) jdk5.0 返回从给定位置开始或结束的代码点 |
int codePointCount(int startIndex,int endindex) jdk5.0 返回startIndex和endIndex-1之间的代码点数量,没有配成对的代用字符将计入代码点。 |
3)字符串处理
String trim() 返回一个新字符串,这个字符串将删除原始字符串头部和尾部的空格。 |
String substring(int beginIndex) String substring(int beginIndex,int endIndex) 返回一个新字符串。这个字符串包含原始字符串中从beginIndex到串尾或endIndex-1的所有代码单元。 |
String replace(CharSequence oldString,CharSequence newString) 返回一个新字符串。这个字符串用newString代替原始字符串中所有的oldString。可以用String或StringBuilder对象作为CharSequence参数。 |
String toLowerCase() 返回一个新字符串,这个字符串将原始字符串中所有大写字母改成小写字母。 |
String toUpperCase() 返回一个新字符串,这个字符串将原始字符串中的所有小写字母改成大写字母。 |
具体内容可参阅API文档。
3.7 构建字符串
有些时候,需要由较短的字符串构建一个长的字符串,采用String对象时每次连接字符串其实都是在构建一个新的String对象,既耗时又浪费空间。使用StringBuilder类可避免这个问题的发生。
使用StringBuilder类进行字符串连接的步骤:
u 首先,构建空的字符串构建器:StringBuilder bulder=new StringBuilder();
u 每次需要添加内容时,调用append方法。
builder.append(ch);// ch is a single character
builder.append(str);// str is a string
u 在需要构建字符串时可以调用toString方法,就可以得到一个String对象。
String comString=builder.toString();
注: Jdk5.0引入了StringBuilder类,它的前身是StringBuffer,其效率略低,但允许采用多线程的方式执行添加或删除字符的操作。如果所有字符串在一个单线程中(通常情况)编辑,则应该用StringBuilder替代它。 这两个类的API是相同的。 |
² 构建字符串的常用API:
StringBuilder() 构造方法:构造一个空的字符串构建器。 |
int length() 返回构建器或缓冲器中的代码单元数量。 |
StringBuilder append(String str) StringBuilder append(char c) 追加一个字符串(或字符)并返回this |
void setCharAt(int i,char c) 将第i个代码单元设置为c |
StringBuilder insert(int offset,String str) StringBuilder insert(int offset,Char c) 在offset位置插入一个字符串(或字符)并返回this |
StringBuilder delete(int startIndex,int endIndex) 删除偏移量从startIndex到endIndex-1的代码单元并返回this |
String toString() 返回一个与构建器或缓冲器内容相同的字符串 |
String和StringBuilder使用方法示例:
|