1. String和StringBulider的使用
通过书中介绍,我们得知如下结论:
- 当使用+连接符将字符串进行拼接的时候,编译器会进行自动优化为使用StringBuilder连接字符串。
- 当在for循环中使用+连接符进行拼接字符串的时候, 每一个for循环都会创建一个Stringbuilder对象。 这样就会产生多个需要垃圾回收器回收的垃圾。效率较低。 这时,建议不要使用+连接符拼接字符串, 而是使用StringBuilder连接字符串。
总结: 当字符串操作比较简单(没有for循环等)时,可以依赖编译器进行优化。 但是如果这个字符串需要使用for循环,那么最好自己创建一个StringBuilder对象,用它来构造最终的结果。
注意: 在使用StringBuilder的时候, 要避免这样写:append( a + ":" + c),这样编译器依然要先处理内部的字符串。这个字符串处理也是创建一个Stringbuilder来处理的。
2. 无意识的递归
这里无意识的递归指的是. 在toString方法中,想要显示对象的内存地址. 不能使用this,而要使用super.toString(). 使用this会导致无线循环. 为什么使用this会导致无限循环呢?看下面的代码中的注释就知道了.
package net.mindview.strings; import java.util.ArrayList; import java.util.List; /** * 无限循环 */ public class InfiniteRecursion { public InfiniteRecursion(){ } @Override String toString() { * 使用this会导致无限循环,为什么呢? * 因为: this前面是一个字符串,后面跟着+,就会想到将this转换为字符串,* 结果转换成字符串就有调用本身的toString方法了,导致了无限循环 */ return " InfiniteRecursion address" + this + \n"; //return " InfiniteRecursion address" + super.toString() + "\n"; } static void main(String[] args) { List<InfiniteRecursion> list = new ArrayList<InfiniteRecursion>(); for(int i=0; i<5; i++){ list.add(new InfiniteRecursion()); } System.out.println(list); } }
正确的做法是将注释行去掉. 使用super.toString()
3. 格式化输出
格式化输出使用System.out.printf() 或者System.out.format();
package net.mindview.strings; SimpleFormat { main(String[] args) { int x = 5double y = 5.332542; System.out.println(Row 1: [" + x + " " + y + ]); 一下两种方式是等价的. System.out.format(Row 1: [%d %f]\n,x,y); System.out.printf( 所有新的格式化功能,都有java.util.Formatter类处理。使用Formatter对象的时候,需要向其构造器传递信息,告诉Formatter,最终的结果输出到哪里。package net.mindview.strings; import java.io.PrintStream; import java.util.Formatter; Turtle { private String name; private Formatter f; Turtle(String name,Formatter f){ this.name = name; this.f = f; } void move(int x,int y){ f.format(%s The Turtle is at (%d.%d)\n main(String[] args) { PrintStream outAlias = System.; Turtle tommy = new Turtle(Tommy",new Formatter(System.out)); Turtle terry = Terry new Formatter(outAlias)); tommy.move(0,0); terry.move(4,1)">8); tommy.move(3,1)">42,1)">3); } }总结:
- 格式化操作符:
语法: %[argument_index$][flags][width][.precision]conversion
格式化操作符以%开头,
含义:
- flags: 是一个"-",这个"-"用来标记数据是左对齐还是右对齐. 默认是右对齐,如果有"-",则表示左对齐
- width:指定某一列的宽度的最小尺寸, 可以应用于任何数据。
- precision:与width相对, 用来指明最大尺寸。precision只对特定数据类型的数据有效
package net.mindview.strings; import java.util.Formatter; Receipt { private double total = ; private Formatter f = new Formatter(System.); 打印标题 printTitle(){ * 含义: 格式化字符串串以%开头 * -: 表示左对齐 * 15: 15表示宽度 * s:表示数据的类型是String * .2:表示保留的小数位数 */ f.format(%-15s %5s %10s\nItemQtyPrice); f.format(------------); } 正文的内容 void print(String name,1)">int qty,1)">double price){ f.format(%-15.15s %5d %10.2f\n price; } 总价 printTotal(){ f.format(%-15s %5s %10.2f\nTax"",total*0.06Total1.06 main(String[] args) { Receipt receipt = Receipt(); receipt.printTitle(); receipt.print(Jack`s Magic Beans4.25); receipt.print(Princess Peas5.1Three Bears Porridge1,1)">14.29); receipt.printTotal(); } }运行结果:
Item Qty Price ---- --- ----- Jack`s Magic Be 4 Princess Peas 3 5.10 Three Bears Por 1 Tax 1.42 ----- Total 25.06
- String.format()
String.format()方法是一个static方法,他接受与Formatter。format()方法一样的参数。返回值是一个String。
4. 正则表达式
直入主题
- 在java中, \\的意思是“我想插入一个正则表达式的反斜线,所以其后的字符具有特殊含义”。例如:如果你想表示一位数字,那么正则表达式应该是\\d,如果你想插入一个普通的反斜线,你应该这样\\\\。如果,换行和制表符之类的东西使用单反斜线。\n\t
- ?:表示0个或者1个
- +: 表示一个或者多个之前的表达式。如:-?\\d+ 表示带有一个或不带有-号的一个或者多个数字。
- (): 表示分组.
- | : 表示或者
- \W:他的意思是非单词字符。注意,这里是大写。 如果小写,表示的时单词字符。
IntegerMatch { main(String[] args) { System.-1234".matches(-?\\d+)); System.5678+991+911(-|\\+)?\\d+)); } }运行结果:
true false true在这里+有特殊的含义,所以,表示普通含义的+需要使用\\将其转义。
- 使用String自带的split分隔字符串
package net.mindview.strings; import java.util.Arrays; Splitting { static String knights = Then,when you have found the shrubbery,you must cut down the mightiest tree in the forest... with... a herring!; split(String regex){ System..println(Arrays.toString(knights.split(regex))); } 表示的时按照空格分割字符串 运行结果:[Then,when,you,have,found,the,shrubbery,must,cut,down,mightiest,tree,in,forest...,with...,a,herring!] split(); 表示按照非单次字符分割字符串--这里的非单次字符是空格和,\\W+这个表示:费单次字符之前带n的地方进行分割字符串 这里的分割符是n空格和n,1)">运行结果:[The,whe,you have found the shrubbery,you must cut dow,the mightiest tree i,the forest... with... a herring!] split(n\\W+); } }
- \W:他的意思是非单词字符。注意,这里是大写。 如果小写w,表示的时单词字符。
- \\W+:非单次字符.
- n\\W+:表示n+非单次字符.
- String自带的工具replace
Replacing { static String s = Splitting.knights; out.println(s.replaceFirst(f\\w+locatedout.println(s.replaceAll(shrubbery|tree|herringbanana)); } }运行结果:
Then,when you have located the shrubbery,you must cut down the mightiest tree in the forest... with... a herring! Then,when you have found the banana,you must cut down the mightiest banana in the forest... with... a banana!
- replaceFirst:表示替换第一个符合条件的字符串。
- replaceAll:表示替换全部符合条件的字符串
- f\\w+:表示以f开头的一个或多个单词字母,注意这里是小写。而且是单词字母。空格不是单词字母
- |:表示的时或者。所以运行结果是替换了三个单词为banana
- Pattern和Matcher
- CharSequence 从CharBuffer,String,StringBuffer,StringBuilder类中抽象出来了字序列的一般化定义。因此, 前面这些类都实现了该接口。多数正则表达式都接受CharSequence类型的参数。
package net.mindview.strings; import java.util.regex.Matcher; import java.util.regex.Pattern; TestRegularExpression { if(args.length < 2){ System.Usage:\njava TestRegularExpression "+characterSequence regularExpression+); System.exit(); } System.Input: \""+ args[0] + \"for(String arg: args){ System.Regular expression: \"" + arg +); 定义一个正则表达式的类对象 Pattern p = Pattern.compile(arg); 使用正则表达式匹配字符串. Matcher m = p.matcher(args[]); 对匹配到的字符串进行处理. while(m.find()){ System.Match \"" + m.group() +\" at positions " + m.start() + -" + (m.end()-1) ); } System.\n\n); } } }输入参数:
* * 输入参数:abcabcabcdefabc "abc+" "(abc)+" "(abc){2,}" * @param args */
运行结果:
Input: abcabcabcdefabc Regular expression: Match " at positions 0-14 Regular expression: abc+abc3-6-12-(abc)+abcabcabc(abc){2,}8Pattern表示的时编译后的结果。