本章重点讲述Java中几个主要的跟字符相关的数据结构类型:字符、字符串(String类)、字符串缓冲类(StringBuffer类)、字符串分解类(StringTokenizer类)和正则表达式(Regular Expression)。深入了解Java已经提供的这些强大字符串数据结构可以使编写文本处理程序更加简单迅速。
本章主要内容
& 字符串的定义和使用
& 字符串缓冲区的使用
& 字符串分解类的使用,对复杂文本进行分解
& 正则表达式的使用
字符是一种通用数据类型,是用单引号括起来的一个字符,如'a'、'A'。在本书第2章已经介绍过了字符,跟字符密切相关的通用数据类型是字符串。字符串常量是用双引号括起来的一串字符,比如"Hello World!\n"。在Java中,字符串常量是作为String类的一个特定的对象来处理的,而不是一个数据,下面就来介绍String类的使用方法。
通常情况下,一个字符串是由一个String语句来产生的,如下所示:
String greeting = "Hello";
或者,
String greeting = new String("Hello");
用"Hello"构造出String类的对象greeting。
或者通过使用一个字符数组的构造语句来产生,如下所示:
char[] bunch = {'H','e','l','l','o'};
String greeting = new String(bunch);
用字符数组bunch的内容来构造字符串greeting。
比较两个字符串内容是否一样,可以使用String类提供的equals( )和equalsIgnoreCase( )两个方法。equals测试两个字符串是否含有相同的字符,equalsIgnoreCase则是忽略字符串中的大小写(Case)来比较两个字符串的。如果内容一致,这两个方法返回true;内容不同,则返回值为false。需要注意的是:在Java早期的版本中,“==”运算符只能用来测试两个字符串是否是相同的字符串实例,而在新的JDK版本中,“==”运算符和equals的效果是一样的。
如果要比较两个字符串的大小关系,即它们按字母序排列的时候谁将排在前面,String类提供了一个compareTo( )方法,它的函数原型如下:
public int compareTo(String str);
它的返回值为一个整型的值,如果返回值为-1,则该字符串位于字符串str的前面;返回值为0,该字符串与str内容一致;返回值为1,该字符串在str后面。
【例5-1】程序示例。
//~ CompareString.java
public class CompareString {
public CompareString(){}
public static void main(String[] args)
{
String strA = "AppleTree";
String strB = "appleTREE";
String strC = "AppleTree";
if (strA == strB) {
System.out.println(strA + " & " + strB +" are the same.");
}
else {
System.out.println(strA + " & " + strB +" are not the same.");
}
if (strA == strC) {
System.out.println(strA + " & " + strC +" are the same.");
}
else {
System.out.println(strA + " & " + strC +" are not the same.");
}
if (strA.equals(strB)) {
System.out.println(strA + " is equals to " + strB);
}
else {
System.out.println(strA + " is not equals to " + strB);
}
if (strA.equals(strC)) {
System.out.println(strA + " is equals to " + strC);
}
else {
System.out.println(strA + " is not equals to " + strC);
}
if (strA.equalsIgnoreCase(strB)) {
System.out.println(strA + "&" + strB + " are the same(nocase).");
}
else {
System.out.println(strA + "&" + strB + " are not the same(nocase).");
}
}
}
输出结果如下:
AppleTree & appleTREE are not the same.
AppleTree & AppleTree are the same.
AppleTree is not equals to appleTREE
AppleTree is equals to AppleTree
AppleTree&appleTREE are the same(nocase).
String类提供一个hashCode( )方法,返回int类型的哈希值,其计算公式如下:
hashcode = s[0]*31^(n-1) + s[1]*31^(n-2) + …+ s[n-1]
公式中的s[i]是字符串中的第i个字符,n是字符串的长度,^是幂运算符号。空字符串的哈希值是0。
//~TestHashCode.java
public class TestHashCode {
public TestHashCode() {}
public static void main(String[] args) {
String str = "abc";
int code = str.hashCode();
System.out.println("the String " + str + " hash code is " + code);
}
}
输出结果如下:
the String abc hash code is 96354
equals( )和hashCode( )这两个函数都是Object类的方法,用于判断对象是否相等。一般来说,如果忽略了其中一种,则必须同时忽略这两种,因为两者之间有必须维持的至关重要的关系。特殊情况是:根据equals( )方法判断,如果两个对象是相等的,则它们必须有相同的hashCode( )值(尽管这通常不是真的)。
要查找某个字符或者子字符串在一个字符串中的位置,Java提供的方法是indexOf( ),这个方法有以下8种重载形式。
public int indexOf(int ch);
查找字符串中第一个Unicode为ch的字符的位置,并返回;如果查找失败,返回-1。
public int indexOf(int ch, int fromIndex);
从fromIndex开始查找到字符串中第一个Unicode为ch的字符的位置,并返回;如果查找失败,返回-1。
public int lastIndexOf(int ch);
查找字符串中最后一个Unicode为ch的字符的位置,并返回;如果查找失败,返回-1。
public int lastIndexOf(int ch, int fromIndex) ;
从fromIndex开始,查找最后一个Unicode为ch的字符的位置,并返回;如果查找失败,返回-1。
public int indexOf(String str);
查找字符串中一个子串为str的位置,并返回;如果查找失败,返回-1。
public int indexOf(String str, int fromIndex);
从fromIndex开始,查找到字符串中一个子串为str的位置,并返回;如果查找失败,返回-1。
public int lastIndexOf(String str);
查找字符串中最后一个子串为str的位置,并返回;如果查找失败,返回-1。
public int lastIndexOf(String str, int fromIndex);
从fromIndex开始,查找最后一个子串为str的位置,并返回;如果查找失败,返回-1。
【例5-2】本例说明这些定位方法的使用。
//~TestIndex.java
public class TestIndex {
public TestIndex() {}
public static void main(String[] args) {
String s = "ssabcdefgabcklabcstabcxyz";
String subs = "abc";
System.out.println("the first 'a' is at " + s.indexOf('a'));
System.out.println("the last 'a' is at " + s.lastIndexOf('a'));
System.out.println("the first 'a' after 10 is at "
+ s.indexOf('a',10));
System.out.println("the last 'a' before 10 is at "
+ s.lastIndexOf('a',10));
System.out.println("the first abc is at " + s.indexOf(subs));
System.out.println("the last abc is at " + s.lastIndexOf(subs));
System.out.println("the first abc after 10 is at "
+ s.indexOf(subs,10));
System.out.println("the last abc before 10 is at "
+ s.lastIndexOf(subs,10));
}
}
程序中用于查找的字符串为"ssabcdefgabcklabcstabcxyz",分别按不同的条件查找'a'和"abc"的位置。运行结果如下。
the first 'a' is at 2
the last 'a' is at 19
the first 'a' after 10 is at 14
the last 'a' before 10 is at 9
the first abc is at 2
the last abc is at 19
the first abc after 10 is at 14
the last abc before 10 is at 9
String类提供了抽取子字符串的方法substring( ),它有以下两种形式:
public String substring(int beginIndex);
返回从beginIndex到字符串结束的子串。这里beginIndex的取值范围应该在区间[0, n]内;如果越界,返回值为空字符串。
public String substring(int beginIndex, int endIndex);
返回beginIndex与endIndex之间的子串。这里beginIndex和endIndex的取值范围也应该在区间[0, n]内,且beginIndex<=endIndex;如果不满足,返回值为空字符串。
【例5-3】程序示例。
//~TestSubstring.java
public class TestSubstring {
public TestSubstring() {}
public static void main(String[] args) {
String str = "This is an apple";
System.out.println("the substring after 11 is " + str.substring(11));
System.out.println("the substring between 8&10 is "
+ str.substring(8,10));
}
}
运行结果如下:
the substring after 11 is apple
the substring between 8&10 is an
非常遗憾的是,由于String类不提供修改自身的方法,因此String类从初始化之后就不能再改变其内容了;如果要使用String类的方法改变一个字符串的内容,必须另外生成一个新的字符串。然而,更方便的方法是使用StringBuffer类来改变字符串的内容而不是使用String类。StringBuffer类的用法在5.2节会有详细叙述。
除了前面介绍的几种方法外,String类中还有以下几种常用的方法:
public int length();
返回值为字符串的长度。
public char charAt(int i);
返回字符串中的第i个字符。
public String replace(char oldChar, char newChar);
这是字符替代的方法,把字符串中的oldChar用newChar替代,并返回替代后的新字符串。
String类还有一系列的valueOf( )方法,将其他类型的变量转化为字符串并返回。
可供转化的变量的类型有:int、float、double、long、char、char[]、Object等。
【例5-4】程序示例。
//~ TestExtraString.java
public class TestExtraString {
public TestExtraString() {}
public static void main(String[] args) {
String str = "This is an apple.";
int slen = str.length();
System.out.println("The length of " + str + " is " + slen);
//打印字符串的长度
for(int i = 0; i < slen; i++) {
System.out.println("No. " + i + " char is: " + str.charAt(i));
//逐一打印每个位置上的字符
}
System.out.println("Change a to b: " + str.replace('a', 'b'));
//将字符串中的'a'改为'b'打印
double d = 3.141529;
String dstr = String.valueOf(d);
System.out.println("the double's String is " + dstr);
//将双精度数转化为字符串并打印
}
}
运行结果如下:
The length of This is an apple. is 17
No. 0 char is: T
No. 1 char is: h
No. 2 char is: i
No. 3 char is: s
No. 4 char is:
No. 5 char is: i
No. 6 char is: s
No. 7 char is:
No. 8 char is: a
No. 9 char is: n
No. 10 char is:
No. 11 char is: a
No. 12 char is: p
No. 13 char is: p
No. 14 char is: l
No. 15 char is: e
No. 16 char is: .
Change a to b: This is bn bpple.
the double's String is 3.141529