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 用正则表达式扫描


posted on 2019-08-01 10:25  Mr.Tan&  阅读(161)  评论(0编辑  收藏  举报

导航