Java编程思想 ch13 字符串

13.1 不可变String

String对象是不可变的。String类中每个看起来会修改String值的方法,实际都是创建了一个新的String对象。

13.2 重载+和StringBuilder

重载操作符的意思是一个操作符被用于特定的类时,被赋予了特殊的意义。用于String的“+”和“+=”是
Java中仅有的两个重载过的操作符,而且java不需要程序员重载任何操作符。问题在于+,会产生新的String对象用于包含原来的两个String对象。(除非你用代码将系统实现,并让它动起来,否则你不会了解有什么问题。)
虽然编译器会为我们优化+为StringBuilder,但在每一次循环中都会新建StringBuiler,所以还是使用StringBuiler好。 包括insert,replace,subString,reverse,append,toString,delete

String result= "";
for(int i=0; i<fields.length;i++)
    result+=fields[i];

13.3 无意识的递归

标准容器覆盖了String方法,用于表达容器自身,以及容器包含的对象。
// 使用this不能完成打印变量内存地址的功能,
import java.util.*;
public class InfiniteRecursion {
    public String toString(){
        return " InfiniteRecursion address:"+this+"\n"
        // 编译器看到String对象跟一个+,而后面不是String对象,会调用this的toString方法,调用自身。改用super.tostring()方法。
    }

    public static void main(String[] args) {
        List<InfiniteRecursion> v = new ArrayList<>();
        for(int i=0; i<10; i++)
            v.add(new InfiniteRecursion());
        System.out.println(v);
    }
}

13.4 String上的操作

方法参数应用
length
charAt
getChars
getBytes
equalsIgnoreCase
compareToString按字典顺序比较String内容,比较结果为负数,0,正数。大小写并不等价。
contains要搜索的CharSequence
contentEqualsCharSquence和StringBuffer
startsWith endsWith
indexOf lastIndexOfchar String
subString
toLowerCase toUpperCase
trim将String两端的空白字符删除

13.5 格式化的输出

13.5.1 printf

printf("Row 1: [%d %f]\n",x,y);

13.5.2 System.out.format()

与printf等价

public class SimpleFormat {
    public static void main(String[] args){
        int x = 5;
        double y = 5.332352
        //The old way,pretty complicated to deal with
        System.out.println("Row 1: ["+x+" "+y+"]");
        // The new way
        System.out.format("Row 1: [%d %f]\n",x,y);
        // or
        System.out.printf("Row 1: [%d %f]\n",x,y);
    }
}

13.5.3 Formatter类

当你新建一个Formatter对象的时候,需要向其构造器传递信息,指出最终结果将向哪里输出。

package Ch12;
import java.io.*;
import java.util.*;
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.out;
        Turtle tommy = new Turtle("Tommy",new Formatter(System.out));
        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);
    }
}
output:
Tommy The Turtle is at (0,0)
Terry The Turtle is at (4,8)
Tommy The Turtle is at (3,4)
Terry The Turtle is at (2,5)
Tommy The Turtle is at (3,3)
Terry The Turtle is at (3,3)

13.5.4 格式化说明符

%[argument_index$][flags][width][.precision]conversion
width指明最小尺寸,Formatter必要时通过添加0,来达到最小尺寸。
默认右对齐,不过可以使用“-”来改变对齐方向。

presion–>与width对应指明最大尺寸。
应用字符时,表示打印的最大字符长度。
应用于浮点,表示小数后面显示出来的部分,默认六位。如果小数过度则舍入,太少则补零。 由于整数没有小数,应用presion,会触发异常。

package Ch12;
import java.util.*;

public class Receipt {
    private double total = 0;
    private Formatter f = new Formatter(System.out);
    public void printTitle(){
        f.format("%-15s %5s %10s\n", "Item", "Qty", "Price");
        //    %-15s,-左对齐,15是width,因为是String后面补空格。 两个元素之间还有一个默认空格。所以一共是16个单位。

        f.format("%-15s %5s %10s\n", "----", "---", "-----");
    }
    public void print(String name, int qty, double price){
        f.format("%-15.15s %5d %10.2f\n", name, qty, price);
        // %-15.15s,与%15s一致,小数点后面15代表最大长度。
        total+=price;
    }
    public void printTotal() {
        f.format("%-15s %5s %10.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();
    }
}

output:
Item              Qty      Price
----              ---      -----
Jack's Magic Be     4       4.25
Princess peas       3       5.10
Three Bears Por     1      14.29
Tax                         1.42
                           -----
Total                      25.06

13.5.5 Formatter转换

header 1代表
d整数型(十进制)
e浮点数(科学计数法)
cUnicode字符
x整数(十六进制)
bBoolean值
h散列码
sString
%字符%
f浮点数(十进制)

将不为null的参数转化为boolean为真,即使0也是真。

13.5.6 String.format()

String.format()内部也是创建一个Formatter对象,然后将你传入的参数转给Formatter对象。
当你需要使用format方法一次时,这个更清晰。

13.6 正则表达式–处理字符串问题

13.6.1 基础

正则表达式就是通过某种方式来描述字符串
\d表示一位数字
在其他语言中,\\表示“在正则表达式中插入普通的反斜线,没有特殊意义。”
在java中则是我要插入一个正则表达式的反斜线,所以其后字符有特殊意义。\\\\
表达普通字符\。 前两个\,表示插入正则式子,后一个\是正则的,最后一个是要插入字符字符。 \\/是/
public class IntegerMatch {
    public static void main(String[] args) {
        System.out.println("-1234".matches("-?\\d+"));
        System.out.println("5678".matches("-?\\d+"));
        System.out.println("+911".matches("-?\\d+"));
        System.out.println("+911".matches("(-|\\+)?\\d+"));
        // | 表示或,()将表达式分组
    }
}
output:
true
true
false
true

String自带的split()和replace方法。
replaceFirst(“regex”,String s);
replaceAll(“regex”,String s);

13.6.2

字符意义
B指定字符B
\xhh十六进制为0xhh的字符
\uhhhh十六进制为 0xhhhh的unicode字符
\t制表符tab
\n换行符
\r回车
\f换页
\e转义(Escape)
字符类意义
.任意字符
[abc]a|b|c
[^abc]除了abc之外的所有字符
[a-zA-Z]从a到z,A到Z的所有字符
[adc[hij]]a
[a-z&&[hij]]任意h,i或j的交。
\s空白字符(空白,tab,换行,换页,回车)
\S非空白字符([^\s])
\d数字[0-9]
\D非数字
\w词字符[a-zA-Z0-9]
\W非词字符[^\w]
边界匹配符meaning
^一行的起始
\B非词的边界
$一行的结束
\G前一个匹配的结束
\b词的边界

13.6.3 量词

描述一个模式吸收输入文本的模式
贪婪型 X? 为所有可能的模式发现尽可能多的匹配
勉强型 X?? 匹配满足模式最少的字符数
占有型 X?+ 只在java中,防止回溯,
header1meaning
X?一个或者零个X
X*或者多个零个X
X+一个或者多个X
X{n}恰好n次X
X{n,}至少n次x
X{n,m]至少n次,至多m次
row 2 col 1row 2 col 2

13.6.4 Pattern和Matcher

Pattern p = Pattern.compile(regex);
        static boolean matches(String regex, CharSequence input)
        split() replace()
Matcher m = p.matcher(testString);
m.matches() testString 是否匹配regex
m.lookingAt() testString 某部分开始是否匹配
m.find()
m.find(int start)
find()在charSequence查找多个匹配字符
package Ch12;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Finding {
    public static void main(String[] args) {
        Matcher m = Pattern.compile("\\w+").matcher("Evening is full of linnet's wings");
        while(m.find()){
            System.out.print(m.group()+" ");
        }
        System.out.println();
        int i=0;
        while(m.find(i)){
            System.out.print(m.group()+" ");
            i++;
        }
    }
}
Evening is full of linnet s wings 
Evening vening ening ning ing ng g is is s full full ull ll l of of f linnet linnet innet nnet net et t s s wings wings ings ngs gs s 
Groups
A(B(C)D) 组0是整个正则表达式 ABCD,组1是BC,组2是C
public int groupCount() 返回匹配器的模式中分组数目,不包括0组
public String group() 返回前一次匹配操作的第0组,
public int start()返回前一次匹配中找到的组的起始索引,
public int end()返回前一次匹配中找到的组的最后一个字符索引+1的值,
pattern 标记

13.6.5 split()

String[] split(CharSequence?? String input)
String[] split(CharSequence?? input, int limit)
package Ch12;
import static  tools.Print.print;
import java.util.*;
import java.util.regex.*;
public class SplitDemo {
    public static void main(String[] args) {
        String input = "This!!unusual use!!of exclamation!!points";
        print(Arrays.toString(Pattern.compile("!!").split(input)));
        print(Arrays.toString(Pattern.compile("!!").split(input,3)));
    }
}
[This, unusual use, of exclamation, points]
[This, unusual use, of exclamation!!points]

13.6.6 替换操作

package ch13;
//: Strings/TheReplacement.java
import java.util.regex.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;

public class TheReplacement {
    public static void main(String[] args) throws Exception{
        String s = "/*! Here's a block text to use as input to " +
                "the regular expression matcher. Note that we'll " +
                "first extract the block of textg by looking for the special delimiters, then process the " +
                "extracted block. !*/";
         //原来是一个文件读取有问题,我直接改成该字符串     
        Matcher mInput = Pattern.compile("/\\*!(.*)!\\*/",Pattern.DOTALL).matcher(s);

        if(mInput.find())
            s = mInput.group(1);
            //replaceFirst和replaceAll是String自带方法。
            //appendReplacement是Matcher类的方法。
        s = s.replaceAll(" {2,}"," ");//将2个或者多个空格替换为1个
        s = s.replaceAll("(?m)^ +","");//每行开头的多个空格去掉。
        print(s);
        s = s.replaceFirst("[aeiou]","(VOWEL1)");

        StringBuffer subf = new StringBuffer();

        Pattern p = Pattern.compile("[aeiou]");
        Matcher m = p.matcher(s);

        while(m.find())
            m.appendReplacement(subf, m.group().toUpperCase());
            m.appendTail(subf);// 所谓剩余未处理实际是处理后的字符串。
            print(subf);
    }

}
output:
Here's a block text to use as input to the regular expression matcher. Note that we'll first extract the block of textg by looking for the special delimiters, then process the extracted block. 
H(VOWEL1)rE's A blOck tExt tO UsE As InpUt tO thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE'll fIrst ExtrAct thE blOck Of tExtg by lOOkIng fOr thE spEcIAl dElImItErs, thEn prOcEss thE ExtrActEd blOck. 

13.6.7 reset()

m.reset()将现有Matcher对象用于新的字符序列
package ch13;
import java.util.regex.*;
public class Resetting {
    public static void main(String[] args) throws Exception{
        Matcher m = Pattern.compile("[frb][aiu][gx]").matcher("fix the rug with bags");
        while(m.find())
            System.out.print(m.group()+" ");
        System.out.println();
        m.reset("fix the rag with rags");
        while(m.find()){
            System.out.print(m.group()+" " +
                    "");
        }
    }

}
output:
fix rug bag 
fix rag rag

13.6.8 正则表达式和java I/O

??

13.7 扫描输入

package ch13;
import java.io.*;
public class SimpleRead {
    public static BufferedReader input = new BufferedReader(new StringReader("Sir Robin of Camelot\n22 1.61803"));
// StringReader 将String转化为可读的流对象。
    public static void main(String[] args) {
        try{
            System.out.println("What is your name");
            String name = input.readLine();
            System.out.println(name);
            System.out.println("How old are you? What is your favorite double");
            System.out.println("(input: <age> <double>)");
            String numbers = input.readLine();
            System.out.println(numbers);
            String[] numArray = numbers.split(" ");
            int age = Integer.parseInt(numArray[0]);
            double favorite = Double.parseDouble(numArray[1]);
            System.out.format("Hi %s \n", name);
            System.out.printf("In 5 years you will be %d.\n", age+5);
            System.out.printf("My favorite is %f", favorite/2);
        }catch (IOException e){
            System.err.println("I/O exception");

        }
    }
}
//Scanner 类
package ch13;
import com.sun.org.apache.xpath.internal.SourceTree;

import java.util.*;
public class BetterRead {
    public static void main(String[] args) {
        Scanner stdin = new Scanner(SimpleRead.input);
        System.out.println("what is your name");
        String name = stdin.nextLine();
        System.out.println(name);
        System.out.println("How old are you?What is your favorite double");
        System.out.println("(input: <age> <double>)");
        int age = stdin.nextInt();
        double favorite = stdin.nextDouble();
        System.out.println(age);
        System.out.println(favorite);
        System.out.printf("Hi %s \n", name);
        System.out.printf("In five years you will be %d \n", age +5);
        System.out.printf("My favorite double is %f,",favorite/2);

    }
}

13.7.1 Sacnner定界符

package ch13;
import java.util.*;
public class ScannerDelimitter {
    public static void main(String[] args) {
        Scanner scanner = new Scanner("12, 42, 78, 99, 42");
        scanner.useDelimiter("\\s*,\\s");
        while(scanner.hasNextInt()){
            System.out.println(scanner.nextInt()
            );
        }
    }
}

12
42
78
99
42

13.7.2 用正则表达式扫描

??

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值