Java基础之十三 字符串
第十三章 字符串
13.1 不可变String
String对象是不可变的。String类中每一个看起来会修改String值得方法,实际上都是创建了一个全新得String对象,以包含修改后得字符串内容。
13.2 无意识得递归
Java中每个类从根本上都是继承自Object,标准容器类自然也不例外。
使用toString()方法打印出对象得内存地址
import java.util.ArrayList;
import java.util.List;
public class InfiniteRecursion
{
public static void main(String[] args)
{
List<AAA> v = new ArrayList<AAA>();
for (int i = 0; i < 10; i++)
v.add(new AAA());
System.out.println(v);
}
}
class AAA
{
public String toString()
{
return " InfiniteRecursion address: " + super.toString() + "\n";
}
}
13.3 格式化输出
printf("Row 1:[%d %f]\n",x,y);
占位符称作格式修饰符,它们说明了插入数据的位置,还说明了插入数据的类型。
format()与printf()是等价的。
13.3.3 Formatter类
当你创建一个Formatter对象的时候,需要向其构造器传递一些信息,告诉它最终结果在哪里输出。
import java.io.PrintStream;
import java.util.Formatter;
public class Turtle
{
private String name;
private Formatter f;
public Turtle(String name, Formatter f) {
this.name = name;
this.f = f;
}
public void move(int x, int y) {
f.format("%s The Turtle is at (%d,%d)\n", name, x, y);
}
public static void main(String[] args) {
PrintStream outAlias = System.err;
Turtle tommy = new Turtle("Tommy",
new Formatter(System.err));
Turtle terry = new Turtle("Terry",
new Formatter(outAlias));
tommy.move(0,0);
terry.move(4,8);
tommy.move(3,4);
terry.move(2,5);
tommy.move(3,3);
terry.move(3,3);
}
}
Formatter的构造器经过重载可以接受多种输出目的地,最常用的还是PrintString(),OutputStream和File。
13.3.4 格式化说明符
%[argument_index$][flags][width][.precision]conversion
width用来控制一个域的最小尺寸。默认下,数据是右对齐,不过可以通过使用“-”标志来改变对齐方向。
precision指示最大大小。用于string表示字符最大数量,用于浮点表示小数部分要显示出来的位数,不可用于整数。
import java.util.*;
public class Receipt
{
private static final int width=15;
private double total = 0;
private Formatter f = new Formatter(System.out);
public void printTitle() {
f.format("%-"+width+"s %"+(width-10)+"s %"+(width-5)+"s\n", "Item", "Qty", "Price");
f.format("%-"+width+"s %5s %10s\n", "----", "---", "-----");
}
public void print(String name, int qty, double price) {
f.format("%-15.15s %5d %10.2f\n", name, qty, price);
total += price;
}
public void printTotal() {
f.format("%-15s %5s %"+(width-5)+".2f\n", "Tax", "", total*0.06);
f.format("%-15s %5s %10s\n", "", "", "-----");
f.format("%-15s %5s %10.2f\n", "Total", "",
total * 1.06);
}
public static void main(String[] args) {
Receipt receipt = new Receipt();
receipt.printTitle();
receipt.print("Jack's Magic Beans", 4, 4.25);
receipt.print("Princess Peas", 3, 5.1);
receipt.print("Three Bears Porridge", 1, 14.29);
receipt.printTotal();
}
}
13.3.5 Formatter转换
import java.math.*;
import java.util.*;
public class Conversion
{
public static void main(String[] args) {
Formatter f = new Formatter(System.out);
char u = 'a';
System.out.printf("%3s : %s\n","u","a");
System.out.println("u = 'a'");
f.format("s: %s\n", u);
// f.format("d: %d\n", u);
f.format("c: %c\n", u);
f.format("b: %b\n", u);
// f.format("f: %f\n", u);
// f.format("e: %e\n", u);
// f.format("x: %x\n", u);
f.format("h: %h\n", u);
int v = 121;
System.out.println("v = 121");
f.format("d: %d\n", v);
f.format("c: %c\n", v);
f.format("b: %b\n", v);
f.format("s: %s\n", v);
// f.format("f: %f\n", v);
// f.format("e: %e\n", v);
f.format("x: %x\n", v);
f.format("h: %h\n", v);
BigInteger w = new BigInteger("50000000000000");
System.out.println(
"w = new BigInteger(\"50000000000000\")");
f.format("d: %d\n", w);
// f.format("c: %c\n", w);
f.format("b: %b\n", w);
f.format("s: %s\n", w);
// f.format("f: %f\n", w);
// f.format("e: %e\n", w);
f.format("x: %x\n", w);
f.format("h: %h\n", w);
double x = 179.543;
System.out.println("x = 179.543");
// f.format("d: %d\n", x);
// f.format("c: %c\n", x);
f.format("b: %b\n", x);
f.format("s: %s\n", x);
f.format("f: %f\n", x);
f.format("e: %e\n", x);
// f.format("x: %x\n", x);
f.format("h: %h\n", x);
Conversion y = new Conversion();
System.out.println("y = new Conversion()");
// f.format("d: %d\n", y);
// f.format("c: %c\n", y);
f.format("b: %b\n", y);
f.format("s: %s\n", y);
// f.format("f: %f\n", y);
// f.format("e: %e\n", y);
// f.format("x: %x\n", y);
f.format("h: %h\n", y);
boolean z = false;
System.out.println("z = false");
// f.format("d: %d\n", z);
// f.format("c: %c\n", z);
f.format("b: %b\n", z);
f.format("s: %s\n", z);
// f.format("f: %f\n", z);
// f.format("e: %e\n", z);
// f.format("x: %x\n", z);
f.format("h: %h\n", z);
}
}
13.3.6 string.format()
String.format()是一个static方法,它接受与Formatter.format()方法一样的参数,但返回一个String对象。
public class DatabaseException extends Exception
{
public DatabaseException(int transactionID, int queryID,
String message) {
super(String.format("(t%d, q%d) %s", transactionID,
queryID, message));
}
public static void main(String[] args) {
try {
throw new DatabaseException(3, 7, "Write failed");
} catch(Exception e) {
System.out.println(e);
}
}
}
String.format()内部也是创建了一个Formatter对象,然后将传入的参数转给Formatter。
13.6 正则表达式
正则表达式提供一种完全通用的方式,来解决字符串匹配,选择,编辑和验证。
13.6.1 基础
使用split()方法分割字符串:
public class Splitting {
public static String knights = "Then, when you have found the shrubbery, you must "
+ "cut down the mightiest tree in the forest... " + "with... a herring!";
public static void split(String regex) {
System.out.println(Arrays.toString(knights.split(regex)));
}
public static void main(String[] args) {
split(" "); // Doesn't have to contain regex chars
split("\\W+"); // Non-word characters
split("n\\W+"); // 'n' followed by non-word characters
QA7.getString();
QA7.E9();
}
}
使用String自带的正则表达式工具替换:
public class Replacing {
static String s = Splitting.knights;
public static void main(String[] args) {
System.out.println(s.replaceFirst("f\\w+", "located"));
System.out.println(s.replaceAll("shrubbery|tree|herring", "banana"));
}
}
13.6.2 创建正则表达式
下面每一个表达式都能匹配字符串"Rudolph":
public class Rudolph {
public static void main(String[] args) {
for (String pattern : new String[] { "Rudolph", "[rR]udolph", "[rR][aeiou][a-z]ol.*", "R.*" })
System.out.println("Rudolph".matches(pattern));
}
}
我们的目的并不是编写最难理解的正则表达式,而是尽量编写能够完成任务的最简单的最必要的正则表达式。
13.6.3 量词
量词描述了一个模式吸收输入文本的方式:
- 贪婪型:
- 勉强型:
- 占有型:
13.6.4 Pattern和Matcher
用static Pattern.compile()方法来编译正则表达式,它会根据String类型的正则表达式生成一个Pattern对象,把你要检索的字符串传入Pattern对象的matcher()方法。matcher()方法会生成一个Matcher对象。
测试正则表达式,看它们是否匹配一个输入字符串:
find()
Matcher.find()方法可用来查找多个匹配:
组
组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式,组号为1表达被一对括号括起的组。
start()与end()
在匹配操作成功后,start()返回先前匹配的其实位置的索引,而end()返回所匹配的最后字符的索引加一的值。
Pattern标记
Pattern类的compile()方法还有一个版本,它接受一个参数,以调整匹配行为:
Pattern Pattern.compile(String regex,int flag)
通过"或"操作符组合多个标记功能:
13.6.5 Split()
Split()方法将输入字符串断开成字符串对象数组。
按照通用边界断开文本:
13.6.6 替换操作
正则表达式特别便于替换文本。
13.6.7 reset()
通过reset()方法,将现有的Matcher对象应用于一个新的字符串序列:
13.6.8 正则表达式与Java I/O
输出的是有匹配的部分以及匹配部分在行中的位置:
17.7 扫描输入
使用Scanner类扫描输入:
13.7.1 Scanner定界符
用正则表达式指定自己所需的定界符:
13.7.2 用正则表达式扫描