Java字符串
这几天看了Java字符串,所以写出来,当做笔记。
一,String与StringBuilder
首先,String是不可变的,StringBuilder是可变的。所以,在使用上肯定是有区别的,当我们一个字符串经常会改变的时候,最好使用StringBuilder,当一个字符串很少改变使用String更佳。下面一个例子比较一个经常改变的字符串在分别使用String和StringBuilder时的性能。
//使用String
public class Test1 {
public static void main(String[] args) {
String str = ""; //差别在这
for (int i = 0;i < 10;i++) {
str = str + i; //差别在这
}
}
}
//使用StringBuilder
public class Test2 {
public static void main(String[] args) {
StringBuilder str = new StringBuilder(); //差别在这
for (int i = 0;i < 10;i++) {
str = str.append(i); //差别在这
}
}
}
把上面的代码转化成汇编格式看一下:
//使用String
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2 //从第33行跳转到这
6: bipush 10
8: if_icmpge 36
11: new #3 // class java/lang/StringBuilder
14: dup
15: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V重复生成许多StringBuilder对象
18: aload_1
19: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: iload_2
23: invokevirtual #6 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
26: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore_1
30: iinc 2, 1
33: goto 5 //跳转到第5行
36: return
//使用StringBuilder
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V初始化一个StringBuilder对象
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: bipush 10
13: if_icmpge 28
16: aload_1
17: iload_2
18: invokevirtual #4 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
21: astore_1
22: iinc 2, 1
25: goto 10 //跳转到第10行
28: return
首先我也不懂汇编,但是上面两个汇编代码的goto能看懂,他就是执行到这后跳转到其他行,就是我们写的那个循环,对,使用String的时候,我们能看到Java帮我们把String换成了StringBuilder,这是Java考虑到性能自己做的优化,但是优化的好不好呢,因为我们使用String,在循环中重复更改一个String,这其实是生成了一系列的String对象,Java优化过后也没改变这个情况,每次循环都要生成一个StringBuilder对象。当我们使用StringBuilder的时候,发现在循环前面生成一个StringBuilder对象,循环内部并没有新对象生成,明显的,这种直接使用StringBuilder是性能更高的。
二,格式化输出
1,最简单的格式化输出
使用System,out.printf();//就像c语言中一样使用。
或者使用System.out.format();
其实前者的实现是调用了后者
2,使用Formatter类
这个类初始化的时候可以设置将输出的东西写入哪里,可以是显示器,文件。
Formatter f = new Formatter(System.out);//标准输出
f.format();//控制输出格式,类似于c,但更强大,例如下面的代码显示时间
Calendar c = new GregorianCalendar();
Formatter f = new Formatter(System.out);
f.format("日期:%1$tY-%1$tm-%1$te\n",c);//%1$代表显示第一个给定数据,t代表显示时间,Yme分别是年份,月份,月内日期
结果例子:日期:2015-06-1
3,构造格式化字符串
使用String.format();返回值是格式化好的字符串,修改上例
Calendar c = new GregorianCalendar();
Formatter f = new Formatter(System.out);
String s = String.format("日期:%1$tY-%1$tm-%1$te",c);
f.format("%s\n",s);