`

第十三章 字符串

阅读更多
2013年8月1日 星期四 21时05分59秒

第十三章 字符串
        可以证明,字符串操作是计算机设计中最常见的行为

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

13.2 重载“+”与StringBuilder
         可以用javap命令来反编译class文件,查看代码是如何工作。
         例如:类Concatenation
                                   package chapter13;
public class Concatenation {
        public static void main(String[] args) {
                String mango="mango";
                String s="abc"+mango+"def"+47;
                System.out.println(s);
        }
}

                通过javap -c Concatenation后,得到如下字节码:
                     D:\Program Files\Java\jdk1.6.0_13\bin>javap -c Concatenation
Compiled from "Concatenation.java"
public class chapter13.Concatenation extends java.lang.Object{
public chapter13.Concatenation();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   ldc     #16; //String mango
   2:   astore_1
   3:   new     #18; //class java/lang/StringBuilder
   6:   dup
   7:   ldc     #20; //String abc
   9:   invokespecial   #22; //Method java/lang/StringBuilder."<init>":(Ljava/la
ng/String;)V
   12:  aload_1
   13:  invokevirtual   #25; //Method java/lang/StringBuilder.append:(Ljava/lang
/String;)Ljava/lang/StringBuilder;
   16:  ldc     #29; //String def
   18:  invokevirtual   #25; //Method java/lang/StringBuilder.append:(Ljava/lang
/String;)Ljava/lang/StringBuilder;
   21:  bipush  47
   23:  invokevirtual   #31; //Method java/lang/StringBuilder.append:(I)Ljava/la
ng/StringBuilder;
   26:  invokevirtual   #34; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
   29:  astore_2
   30:  getstatic       #38; //Field java/lang/System.out:Ljava/io/PrintStream;
   33:  aload_2
   34:  invokevirtual   #44; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   37:  return
}
             由此可知,编译器创建了一个StringBuilder对象,用于构造最终的String。
             注解:dup指令是复制之前分配的java/lang/StringBuilder空间的引用并压入栈顶,invokevirtual指令通过22这个常量池入口需找到了java/lang/                                StringBuilder.append()方法,构造方法虽然找到了。但是必须还得知道是谁的构造方法,所以要将之前分配的空间的应用压入栈顶让                                     invokespecial命令应用才知道原来这个构造方法是刚才创建的那个引用的,调用完成之后将栈顶的值弹出。之后调用astore_1将此时的栈顶值弹出                          存入局部变量中去。

13.3 无意识的递归
                                    package chapter13;
import java.util.ArrayList;
import java.util.List;
/*@name InfiniteRecursion.java
* @describe  13.3 无意识的递归
* @since 2013-08-03 00:06
* @author 张彪
*/
public class InfiniteRecursion {
        public String toString(){
                return "InfiniteRecursion"+ this +"\n";  //this应该改为super.toString()
        }
        public static void main(String[] args) {
                List<InfiniteRecursion> list=new ArrayList<InfiniteRecursion>();
                for(int i=0;i<3;i++){
                        list.add(new InfiniteRecursion());
                }
                System.out.println(list.toString());
        }
}
//报错
/*Exception in thread "main" java.lang.StackOverflowError
        at java.lang.StringBuilder.append(StringBuilder.java:119)
        at java.lang.StringBuilder.<init>(StringBuilder.java:93)*/          

                        报错原因是由于编译器看到一个String对象之后跟一个“+”号,而后边的对象不是String类型,于是编译器试图将this转换成一个String。正式通过调用this上的                             toString()方法,于是发生了递归调用。
                        如果你这的想打印对象的内存地址,应该用Object.toString()方法。这才是负责此任务的方法。

13.4 String上的操作
                String对象的常用方法。
                String类的方法都会返回一个新的String对象。同时,如果内容没发生改变,String()方法只是返回指向原对象的引用而已。

13.5 格式化输出
        13.5.1 printf()
        13.5.2 System.out.format()
                J2SE5引入的format()方法。format()方法模仿于C的printf()方法。
                                        package chapter13;
public class SimpleFormat {
        public static void main(String[] args) {
                int x=5;
                float y=4.5f;
                System.out.println(x+" "+y);
                System.out.printf("%d,%f\n",x,y);
                System.out.format("%d,%f",x,y );
        }
}

        13.5.3 Formatter类 
        13.5.4 格式化说明符
                                      package chapter13;
import java.util.Formatter;
/*@name Receipt.java
* @describe  13.5.4 格式化说明符
* @since 2013-08-03 01:24
* @author 张彪
*/
//打印一个购物收据
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");
                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);
                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 t=new Receipt();
                t.printTitle();
                t.print("Jack's Magic Bean", 4, 4.25);
                t.print("Princess Peas", 3, 5.1);
                t.printTotal();
        }


Formatter提供了对空格与对其的强大功能。

        13.5.5 Formatter转换       
        13.5.6 String.format()

13.6 正则表达式
               正则表达式是一种强大而灵活的文本处理工具。
        13.6.1 基础
                \d 表示一位数字
                在 Java中,"\\"的意思是我要插入一个正则表达式的反斜线。
                -?\\d+  表示可能有一个负数,后面有多个数字

        13.6.2  创建正则表达式    
        13.6.3  量词
                量词描述一个模式吸收输入文本的方式
                        贪婪型:
                        勉强型:用?号来指定,
                        占有型:

                charSequence 接口。
                                                                                       
                                        package chapter13;
import java.util.Arrays;

/*@name IntegerMatch.java
* @describe  13.6 正则表达式
* @since 2013-08-03 10:24
* @author 张彪
*/
public class IntegerMatch {
        public void match1(){
                System.out.println("-123".matches("-?\\d+"));  //true
                System.out.println("-a3".matches("-?\\d+"));   //false
                //"+"在正则表达式有特殊的意义,所以这个地方要用转义
                System.out.println("+56".matches("(-|\\+)?\\d+")); //true
        }
        public void splitMethod(){
                String knights="Tree in the fores... wih ....a herring!";
                String regex1="\\w+";
                System.out.println(Arrays.toString(knights.split(" "))); //以" "进行分割
                System.out.println(Arrays.toString(knights.split("\\W"))); // "\W"意思是非单词字符 ,"\w"表示一个单词字符
                System.out.println(Arrays.toString(knights.split("n\\W+"))); //表示字母n后面跟着一个或多个非单词字符
                //split(regex, limit) 重载方法, 第二个参数为限制分割的次数
        }
        public void replaceMethod(){
                System.out.println("abc".replaceFirst("a|b|c","uu")); //uubc
        }
        //创建正则表达式
        public void createRegex(){
                for(String  patter:new String[]{"Rudolph","[rR]udolph","[rR][aeiou][a-z]ol.*","R.*"}){
                        System.out.println("Rudolph".matches(patter));
                }
        }
        public static void main(String[] args) {
                new IntegerMatch().createRegex();
        }
}
               
        13.6.4  Patter和Matcer
                Matcher.find()方法可以在CharSequence中查找多个匹配。
                                    package chapter13.string;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Finding {
        public void findMethod(){
                //模式  "\\w+" 将字符串划分为单词
                Matcher m=Pattern.compile("\\w+").matcher("Evening is full of the linet'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++;
                }
        }
        public static void main(String[] args) {
                new Finding().findMethod();
        }
}

                组(Groups)
                       组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式。
                                               
                start()和end()
                Pattern标记
                                      package chapter13.string;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReFlags {
        public static void main(String[] args) {
                Pattern p=Pattern.compile("^java", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE);
                Matcher m=p.matcher("java has regex\nJava has regex\n" +
                                "JAVA has regex\n" +
                                "Regular exression are in Java");
                while(m.find()){
                        System.out.println(m.group()+"-");
                }
        }
}
/*java-
Java-
JAVA-*/
该例子中的模式将匹配以"java,Java,JAVA"等开头的行。注意group()方法只返回已匹配的部分。

        13.6.5 split()方法
                        split()方法将输入字符串断开成字符串对象数组,断开边界由下列正则表达式确定。
                                                package chapter13.string;
import java.util.Arrays;
import java.util.regex.Pattern;
public class SplitDemo {
        public static void main(String[] args) {
                String input="This!!unusal use!!of exclamation!!points";
                System.out.println(Arrays.toString(Pattern.compile("!!").split(input)));  //[This, unusal use, of exclamation, points]
                //第二个参数可以限制分割成字符串的数量
                System.out.println(Arrays.toString(Pattern.compile("!!").split(input,3))); //[This, unusal use, of exclamation!!points]
        }
}                       

        13.6.6  替换操作
                        replaceFirst(),replaceALl(),appendReplacement()..........
        13.6.7  reset()               
        13.6.8  正则表达式与Java I/O

13.7 扫描输入
           Scanner类
                 Scanner类在 Java SE5中新增的类。
                                             package chapter13.string;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.Scanner;
public class BetterRead {
        public static void main(String[] args) {
                Scanner scanner=new Scanner(new BufferedReader(new StringReader("Sir Robin of Camelot\n22 1.61803")));
                System.out.println(scanner.nextLine());   //Sir Robin of Camelot
                System.out.println(scanner.nextInt());    //22
        }
}
                                     
     13.7.1 Scanner定界符
                    Scanner默认情况下根据空白字符对输入进行分词。但是你也可以根据正则表达式进行指定自己所需要的定界符
                                          package chapter13.string;
import java.util.Scanner;
public class ScannerDelmiter {
        public static void main(String[] args) {
                Scanner scanner=new Scanner("12,34,56,78");
                scanner.useDelimiter("\\s*,\\s*");
                while(scanner.hasNext()){
                        System.out.println(scanner.nextInt());
                }
                       
        }
}

     13.7.2 用正则表达式扫描   
                             
13.8 StringTokenizer
        有了正则表达式和Scanner之后,StringTokenizer基本上可以废弃不用了。

13.9 总结 

       个人总结: 通过这章的学习,对正则表达式有了新的认识。。。。。。。。。。

       
               

                                                                                                    2013-08-06 0:47 记 @jinrongdajie31.xichengqu.beijing
                                                                                                                        
0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics