《Java编程思想》第十三章 字符串

£可爱£侵袭症+ 提交于 2019-12-22 00:41:17

可以证明,字符串操作是计算机程序设计中最常见的行为。

不可变String

String对象是不可变的。例如:

public class Immutable{
   public static String upcase(String s){
         return s.toUpperCase();
}
public static void main(String[] args){
      String q = "howday";
      print(q);
      String qq = upcase(q);
      print(qq);
      print(q);
}
}
howday
HOWDAY
howday

当把q传给upcase()方法时,实际传递的是引用的一个拷贝。其实,每当把String对象作为方法的参数时,都会复制一份引用,而该引用指向的对象其实一直待在一个单一的物理位置上,从未动过。

重载“+”与StringBuilder

操作符+号可以用来连接String。当你为一个类编写toString方法时,如果字符串操作比较简单,那就可以信赖编译器,但是,如果要在toString的方法中使用循环,那么最好自己创建一个StringBuilder对象,用它来构造最终的结果。

无意识的递归

Java中的每个类从根本上都是继承自Object,标准容器类自然也不例外。因此容器类都有toString()方法,并且覆写了该方法。如果想要打印出对象的内存地址,应该调用super.toString()方法。

格式化输出

Java SE5中引入的format()方法可用于PrintStream或PrintWriter对象,其中也包括System.out对象。format()方法模仿自C的printf()。format与printf是等价的。

Formatter类

在Java中,所有新的格式化功能都由java.util.Formatter类处理。当你创建一个formatter对象的时候,需要向其构造器传递一些信息,告诉它最终的结果将向哪里输出。Formatter的构造器经过重载可以接受多种输出目的地,不过最常用的还是PrintStream()、OutputStream和File。

格式化说明符

在插入数据时,如果想要控制格式与对其,需要更精细复杂的格式修饰。
%[argument_index$][flags][width][.precison]conversion
最常见的应用是控制一个域的最小尺寸,,这可以通过指定width来实现。Formatter对象在必要时添加空格,来确保一个域至少达到某个长度。在默认的情况下,数据是右对齐,不过可以通过使用“-”标志来改变对其方向。于width相对的是precision,它用来指明最大尺寸。width可以应用于各种类型的数据转换,并且其行为方式都一样。precision则不然,不是所有类型的数据都能使用precision。在将precision应用于string类型是,它表示打印String时输出字符的最大数量。而在将precision应用于浮点数时,它表示小数部分要显示出来的位数(默认是6位),如果小数位数过多则舍入,太少补0。由于整数没有小数部分,所有precision无法应用于整数,如果对整数应用precision,则会触发异常。例如:

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("%-15.15s %5s %10.2f\n","Tax","",total*0.06);
          f.format("%-15.15s %5s %10.2f\n","","","-----");
          f.format("%-15.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();
}
}
Item                       Oty           Price
----                       ---           ------
Jack's Magic Be              4            4.25
Princess Peas                3            5.10
....
                   

Formatter转化

d 整数型(十进制);c Unicode字符;b Boolean值;s String;f 浮点数(十进制);e 浮点数(科学计数);x 整数(十六进制);h 散列码(十六进制);% 字符“%”
在类型转换中,b转换对各种类型都是合法的,但是其行为却不一定于你想象的一致。对于boolean基本类型,其转换结果是对应的truefalse。但是,对于其他类型的参数,只要该参数不为null,那转换的结果就永远都是true。即使是数字0,转换结果依然为true,而这在其他语言中,往往转换为false。

正则表达式

一般来说,正则表达式就是以某种方式来描述字符串。例如,要找一个数字,它可能有一个负号在最钱买你,那你就写一个负号加上一个问号:-?。
如果你想表示一位数字,那么正则表达式应该是\d。如果你想插入一个普通的反斜杠,则应该是这样\\。不过换行和制表符之类的东西只需使用单反斜线:\n\t。
要表示“一个或多个之前的表达式”,应该使用+。所以,如果要表示”可能有一个负号,后面跟着一位或多位数字“,可以这样:-?\d+
String类自带了一个非常有用的正则表达式工具----split()方法,其功能是”将字符串从正则表达式匹配的地方切开。“

public classSplitting{
     public static String knights = 
          "Then , when you have found the shrubbery , you must " + 
     "cut down the minghtiest 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(" ");
      split("\\W+");
      split("n//W+");
}
}
[Then , , when, you, have, found, the, shrubbery, , you, must, 
cut, down, the, mightiest, tree, in, the, forest ...,
with ... , a, herring!]
[Then , when, you, have, found, the, shrubbery, you, must, 
cut, down, the, mightiest, tree, in, the, forest,
with, a, herring]
[The , whe, you, have, found, the, shrubbery, , you, must, 
cut, dow, the, mightiest, tree, i, the, forest,
with, a, herring]

第一个split()只是按空格来划分字符串。
第二个和第三个split()都用到了\W,它的意思是非单词字符(如果W小写,\w,则表示一个单词字符。)通过第二个例子可以看出,它将标点字符删除了。第三个Split()表示“字母n后面跟着一个或多个非单词字符”。可以看到,在原始字符串中,于正则表达式匹配的部分,在最终结果中都不存在了。
B 指定字符B;\xhh 十六进制值为oxhh的字符;\uhhhh 十六进制表示为oxhhhh的Unicode字符;\t 制表符;\n换行符;\r 回车;\f 换页; \e 转义。
字符类:
. 任意字符
[abc] 包含a,b 和c的任何字符(和a|b|c作用相同)
[^abc] 除了a,b 和c之外的任何字符(否定)
[a-zA-Z] 从a到z或从A到Z的任何字符(范围)
[abc[hij]] 任意a,b,c,h,i,j字符(与a|b|c|h|i|j作用相同)
[a-z&&[hij]] 任意h,i,j(交)
\s 空白符
\S 非空白符
\d 数字【0-9】
\D 非数字
\w 词字符[a-zA-Z0-9]
\W 非词字符

量词

量词描述了一个模式吸收输入文本的方式:
贪婪型:量词总是贪婪的。有其他的选项被设置。
勉强型:用问号来指定,这个量词匹配满足模式所需的最少字符数。
占有型目前,这种类型的量词只有在Java语言中才可用,并且也更高级。

组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式,组号1表示被第一对括号括起的组,依此类推。因此,在下面这个表达式,A(B©)D中有三个组:组0是ABCD,组1是BC,组2是C。
start()返回先前匹配的其实位置的索引,而end()返回所匹配的最后字符的索引加一的值。
注意,find()可以在输入的任意位置定位正则表达式,而lookingAt()和matches()只有在正则表达式与输入的最开始处就开始匹配才会成功。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!