字符串
字符串的常用性应该属于top3
// strings/Concatenation.java public class Concatenation { public static void main(String[] args) { String mango = "mango"; String s = "abc" + mango + "def" + 47; System.out.println(s); } } /* Output: abcmangodef47 */
public static void main(java.lang.String[]); Code: Stack=2, Locals=3, Args_size=1 0: ldc #2; //String mango 2: astore_1 3: new #3; //class StringBuilder 6: dup 7: invokespecial #4; //StringBuilder."<init>":() 10: ldc #5; //String abc 12: invokevirtual #6; //StringBuilder.append:(String) 15: aload_1 16: invokevirtual #6; //StringBuilder.append:(String) 19: ldc #7; //String def 21: invokevirtual #6; //StringBuilder.append:(String) 24: bipush 47 26: invokevirtual #8; //StringBuilder.append:(I) 29: invokevirtual #9; //StringBuilder.toString:() 32: astore_2 33: getstatic #10; //Field System.out:PrintStream; 36: aload_2 37: invokevirtual #11; //PrintStream.println:(String) 40: return
编译器自动引入了 java.lang.StringBuilder
类。虽然源代码中并没有使用 StringBuilder
类,但是编译器却自作主张地使用了它,就因为它更高效。
// strings/WhitherStringBuilder.java public class WhitherStringBuilder { public String implicit(String[] fields) { String result = ""; for(String field : fields) { result += field; } return result; } public String explicit(String[] fields) { StringBuilder result = new StringBuilder(); for(String field : fields) { result.append(field); } return result.toString(); } }
implicit
public java.lang.String implicit(java.lang.String[]); 0: ldc #2 // String 2: astore_2 3: aload_1 4: astore_3 5: aload_3 6: arraylength 7: istore 4 9: iconst_0 10: istore 5 12: iload 5 14: iload 4 16: if_icmpge 51 19: aload_3 20: iload 5 22: aaload 23: astore 6 25: new #3 // StringBuilder 28: dup 29: invokespecial #4 // StringBuilder."<init>" 32: aload_2 33: invokevirtual #5 // StringBuilder.append:(String) 36: aload 6 38: invokevirtual #5 // StringBuilder.append:(String;) 41: invokevirtual #6 // StringBuilder.toString:() 44: astore_2 45: iinc 5, 1 48: goto 12 51: aload_2 52: areturn
可见在循环里新建了n次StringBuilder
explicit
public java.lang.String explicit(java.lang.String[]); 0: new #3 // StringBuilder 3: dup 4: invokespecial #4 // StringBuilder."<init>" 7: astore_2 8: aload_1 9: astore_3 10: aload_3 11: arraylength 12: istore 4 14: iconst_0 15: istore 5 17: iload 5 19: iload 4 21: if_icmpge 43 24: aload_3 25: iload 5 27: aaload 28: astore 6 30: aload_2 31: aload 6 33: invokevirtual #5 // StringBuilder.append:(String) 36: pop 37: iinc 5, 1 40: goto 17 43: aload_2 44: invokevirtual #6 // StringBuilder.toString:() 47: areturn
只新建一次,这说明即使编译器足够聪明,但是也并非任何操作都能优化。
意外递归,不要使用this来打印地址
// strings/ArrayListDisplay.java import java.util.*; import java.util.stream.*; import generics.coffee.*; public class ArrayListDisplay { public static void main(String[] args) { List<Coffee> coffees = Stream.generate(new CoffeeSupplier()) .limit(10) .collect(Collectors.toList()); System.out.println(coffees); } } /* Output: [Americano 0, Latte 1, Americano 2, Mocha 3, Mocha 4, Breve 5, Americano 6, Latte 7, Cappuccino 8, Cappuccino 9] */
// strings/InfiniteRecursion.java // Accidental recursion // {ThrowsException} // {VisuallyInspectOutput} Throws very long exception import java.util.*; import java.util.stream.*; public class InfiniteRecursion { @Override public String toString() { return " InfiniteRecursion address: " + this + "\n" } public static void main(String[] args) { Stream.generate(InfiniteRecursion::new) .limit(10) .forEach(System.out::println); } }
这里会报错,因为string + 会将后面的对象也转为string,然后就又跳到tostring方法,发生了递归死循环。
如果你真的想要打印对象的内存地址,应该调用 Object.toString()
方法,这才是负责此任务的方法。所以,不要使用 this
,而是应该调用 super.toString()
方法。
public class InfiniteRecursion { @Override public String toString() { return " InfiniteRecursion address: " + super.toString() + "\n"; } public static void main(String[] args) { Stream.generate(InfiniteRecursion::new) .limit(10) .forEach(System.out::println); } }
一些通用的方法api自行查找
格式化输出
在 Java 中,所有的格式化功能都是由 java.util.Formatter
类处理的。可以将 Formatter
看做一个翻译器,它将你的格式化字符串与数据翻译成需要的结果。当你创建一个 Formatter
对象时,需要向其构造器传递一些信息,告诉它最终的结果将向哪里输出:
// strings/Turtle.java import java.io.*; import java.util.*; public class Turtle { private String name; private Formatter f; public Turtle(String name, Formatter f) { this.name = name; this.f = f; } public void move(int x, int y) { f.format("%s The Turtle is at (%d,%d)%n", name, x, y); } public static void main(String[] args) { PrintStream outAlias = System.out; Turtle tommy = new Turtle("Tommy", new Formatter(System.out)); Turtle terry = new Turtle("Terry", new Formatter(outAlias)); tommy.move(0,0); terry.move(4,8); tommy.move(3,4); terry.move(2,5); tommy.move(3,3); terry.move(3,3); } } /* Output: Tommy The Turtle is at (0,0) Terry The Turtle is at (4,8) Tommy The Turtle is at (3,4) Terry The Turtle is at (2,5) Tommy The Turtle is at (3,3) Terry The Turtle is at (3,3) */
StringTo'kenizer类,分词用的,字符串的一大部分是正则的使用,这块我的智商较低,基本靠查。
// strings/ReplacingStringTokenizer.java import java.util.*; public class ReplacingStringTokenizer { public static void main(String[] args) { String input = "But I'm not dead yet! I feel happy!"; StringTokenizer stoke = new StringTokenizer(input); while(stoke.hasMoreElements()) System.out.print(stoke.nextToken() + " "); System.out.println(); System.out.println(Arrays.toString(input.split(" "))); Scanner scanner = new Scanner(input); while(scanner.hasNext()) System.out.print(scanner.next() + " "); } } /* Output: But I'm not dead yet! I feel happy! [But, I'm, not, dead, yet!, I, feel, happy!] But I'm not dead yet! I feel happy! */
一个没有高级趣味的人。
email:hushui502@gmail.com