java-字符串
1、String对象是不可变的,JDK源码的类的定义如下:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { //... }
不可变的特性会带来一定的效率问题。比如“+”或“+=”操作字符串带来的性能。
示例1:
package com.zifuchuan; public class MyTe { public static void main(String[] args) { String mango="mango"; String b="abc"+mango+"def"+69; System.out.println(mango); } }
使用jdk的命令javap -c反编译,从以下结果可以看到,程序创建了一个StringBuilder对象,并使用append方法拼接,最后将对象转换成最终字符串。编译器自动(优化)使用了Stringbuiltder,由于它更高效。
Compiled from "MyTe.java" public class com.zifuchuan.MyTe { public com.zifuchuan.MyTe(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc #2 // String mango 2: astore_1 3: new #3 // class java/lang/StringBuilder 6: dup 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 10: ldc #5 // String abc 12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: aload_1 16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: ldc #7 // String def 21: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: bipush 69 26: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 29: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 32: astore_2 33: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream; 36: aload_1 37: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 40: return }
示例2:
package com.zifuchuan; public class MyTe2 { public static void main(String[] args) { String result = ""; for (int i=1; i<10; i++){ result+=i; } System.out.println(result); } }
使用jdk的命令javap -c反编译,从以下结果可以看到,程序在循环体内部每次都创建了一个StringBuilder对象。虽然自动使用了StringBuilder,但是每个循环都创建了对象。
Compiled from "MyTe2.java" public class com.zifuchuan.MyTe2 { public com.zifuchuan.MyTe2(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc #2 // String 2: astore_1 3: iconst_1 4: istore_2 5: iload_2 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 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 36: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 39: aload_1 40: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 43: return }
示例3:
package com.zifuchuan; public class MyTe4 { public static void main(String[] args) { StringBuilder result = new StringBuilder(); for (int i=1; i<10; i++){ result.append(i); } System.out.println(result); } }
自建StringBuilder对象拼接字符串,反编译结果显示了只创建了1次StringBuiler对象,并实现了字符串拼接
Compiled from "MyTe4.java" public class com.zifuchuan.MyTe4 { public com.zifuchuan.MyTe4(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return 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 7: astore_1 8: iconst_1 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: pop 22: iinc 2, 1 25: goto 10 28: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 31: aload_1 32: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 35: return }
2、无意识的递归
错误的使用:
package com.zifuchuan; public class MyTe5 { public static void main(String[] args) { MyTe5 myTe5=new MyTe5(); System.out.println(myTe5.toString()); } @Override public String toString() { return "当前对象的地址"+this; } }
正确的使用:
package com.zifuchuan; public class MyTe5 { public static void main(String[] args) { MyTe5 myTe5=new MyTe5(); System.out.println(myTe5.toString()); } @Override public String toString() { return "当前对象的地址"+super.toString(); } }
3、常用方法
package com.zifuchuan; public class MyTe7 { public static void main(String[] args) { String str="abcdefg"; System.out.println(str.length()); System.out.println(str.charAt(1)); System.out.println(str.toCharArray()); System.out.println(str.equals("abcdefg")); System.out.println(str.equalsIgnoreCase("AbcdefG")); System.out.println(str.compareTo("bcdefg")); System.out.println(str.compareToIgnoreCase("Bcdefg")); System.out.println(str.indexOf('g')); System.out.println(str.indexOf("fg")); System.out.println(str.lastIndexOf('g')); System.out.println(str.lastIndexOf("fg")); System.out.println(str.startsWith("ab*")); System.out.println(str.endsWith("fgh*")); System.out.println(str.substring(1)); System.out.println(str.substring(1,3)); System.out.println(String.valueOf(123)); } }
4、格式化 -- 使得数据转换为预定的格式字符串
Formatter类
- 常规类型、字符类型和数值类型的格式说明符的语法如下:
%[argument_index$][flags][width][.precision]conversion
可选的 argument_index 是一个十进制整数,用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用,第二个参数由 "2$" 引用,依此类推。
可选 flags 是修改输出格式的字符集。有效标志集取决于转换类型。
可选 width 是一个非负十进制整数,表明要向输出中写入的最少字符数。
可选 precision 是一个非负十进制整数,通常用来限制字符数。特定行为取决于转换类型。
所需 conversion 是一个表明应该如何格式化参数的字符。给定参数的有效转换集取决于参数的数据类型。
- 示例
package com.zifuchuan; import java.util.Formatter; public class MyTe3 { public static void main(String[] args) { Formatter formatter = new Formatter(System.out); formatter.format("%-10s %-6.8s %9.2f \n", "ab", "gf", 45.678); formatter.format("%5c \n", 'a'); formatter.format("%10b\n", true); System.out.println(String.format("%5c \n", 'v')); //String的格式方法format的使用 } }
5、正则表达式
- Pattern类
package com.zifuchuan; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MyTe6 { public static void main(String[] args) { //只匹配一次的用法 Boolean value2=Pattern.matches("a*b","aaab"); System.out.println(value2); //多次匹配的用法,获取matcher对象可多次匹配 Pattern pattern=Pattern.compile("xy"); Matcher matcher=pattern.matcher("xy"); Boolean value=matcher.matches(); System.out.println(value); //匹配并替换 Matcher matcher1=pattern.matcher("xyuuxy"); String out1=matcher1.replaceFirst("#beijing1#"); System.out.println(out1); Matcher matcher2=pattern.matcher("xu"); String out2=matcher2.replaceFirst("#beijing2#"); System.out.println(out2); Matcher matcher3=pattern.matcher("xyuuxy"); String out3=matcher3.replaceAll("#beijing1#"); System.out.println(out3); //分割 String[] str = pattern.split("xyuuuxyuuuxyuuu"); System.out.println(Arrays.toString(str)); } }
输出结果:
true true #beijing1#uuxy xu #beijing1#uu#beijing1# [, uuu, uuu, uuu]
Pattern对象表示的是正则表达式;从对象的matcher获取的对象matcher表示,与正则表达式进行匹配的对象以及正则表达式。
- String类
package com.zifuchuan; import java.util.Arrays; public class MyTe6 { public static void main(String[] args) {
//分割 String[] str1 = "ss6sasssbsss".split("s"); System.out.println(Arrays.toString(str1));
//替换 String str2 = "bcadafg".replaceFirst("a","2018"); System.out.println(str2); String str3 = "bcadafg".replaceAll("a","2018"); System.out.println(str3); } }
输出结果:
[, , 6, a, , , b]
bc2018dafg
bc2018d2018fg