String对象是JAVA语言中重要的数据类型,但是不是基本数据类型,属于引用数据类型
任何一Project中,无疑字符串的操作是最多的了
String的内部结构:char数组,offset偏移量,count长度
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count;
<span style="white-space:pre"> </span>。。。
public String() { this.offset = 0; this.count = 0; this.value = new char[0]; }
public String(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; }
public String(char value[]) { int size = value.length; this.offset = 0; this.count = size; this.value = Arrays.copyOf(value, size); }
public String(char value[], int offset, int count) { if (offset < 0) { throw new StringIndexOutOfBoundsException(offset); } if (count < 0) { throw new StringIndexOutOfBoundsException(count); } // Note: offset or count might be near -1>>>1. if (offset > value.length - count) { throw new StringIndexOutOfBoundsException(offset + count); } this.offset = 0; this.count = count; this.value = Arrays.copyOfRange(value, offset, offset+count); }
....
String不变性,是指String对象一旦生成,就不能对它进行修改,即这个对象的状态在对象创建时就固定不变了,相当于不变模式(当一个对象被多线程共享时,并且频繁访问,可以省略同步和锁等待时间)。
String对常量池(字符串池)的优化
String s = "1";
s = s+"2";
s = s+"3";
以上这段代码,编译后,我们可以反编译看看编译后的代码是什么样子的
public static void main(String args[])
{
String s = "1";
s = (new StringBuilder()).append(s).append("2").toString();
s = (new StringBuilder()).append(s).append("3").toString();
}
以上因为编译期,不能得出最终的s是什么样子的,所以内部使用了StringBuilder优化
String s = "1"+"2"+"3";
-->
String s = "123";
在编译期知道s是什么样子的,所以直接优化
在常量池中,当两个String对象拥有相同的值时,它们引用常量池中的同一个拷贝,当同一个字符串反复出现时,可以节省大量内存空间
String str1="123";
String str2="123";
String str3=new String("123");
str1和str2是指向同一块内存地址空间,而str3则是另一块内存地址空间,但是最终都指向常量池中的同一个“123”字符串
使用indexOf()和substring()代替split(),效率更高
使用charAt()代替startsWith(),endsWith(),效率更高
public static Object[] mySplit(String source,String s) { List<String> list = new ArrayList<String>(); int loc=source.indexOf(s),length=source.length(); String temp = ""; while(loc!=-1) { temp = source.substring(0, loc); list.add(temp); source=source.substring(loc+1, length); loc = source.indexOf(s); length=source.length(); } return list.toArray(); }
public static void main(String args[]) { String str = "KJDKGF-sdfgdssdfb-5241354651"; int count = 10000000; String temp = ""; long begin = System.currentTimeMillis(); for(int i=0;i<count;i++) { temp = str.split("-")[0]; } System.out.println(System.currentTimeMillis()-begin); begin = System.currentTimeMillis(); for(int i=0;i<count;i++) { temp = str.substring(0,str.indexOf("-")); } System.out.println(System.currentTimeMillis()-begin); }
10000000次操作,从以下结果可以很明显的看出来的性能的差异,在计算机的世界里1ns都应该珍惜啊
1365
129