一、不可变字符序列——String(final类)
【字符串的本质:是字符数组或者是字符序列 】
- 字符串的两种创建方式
方式一:通过字面量或者字面量字符串通过”+”拼接的方式创建的String对象存储在常量池中,实际创建时如果常量池中存在,则直接返回引用,如果不存在则创建该字符串对象。
String str="abc";
方式二:使用构造函数创建字符串对象,则直接在堆中创建一个String对象。
String str1=new String("abc") - 常用方法
2.1 equals()
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
2.2 hashCode()
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
这h = 31 * h + val[i]中,为什么用31?
首先hash函数必须要选用质数(质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数又称为素数),这个是被科学家论证过的hash函数减少冲突的一个理论。
如果设置为偶数的话会存在溢出的情况,导致信息丢失(因为使用偶数相当于使用了移位运算)
可以兼顾到虚拟机的性能,虚拟机默认使用2<<5-1来的到很好的性能,且其是一个不大不小的质数,兼顾了性能和冲突率
2.3 intern()
String的intern()方法会得到字符串对象在常量池中和它相等的字符串的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用。String a="abc"; String b=new String("abc"); System.out.println(a==b);//==比较的是地址 System.out.println(a.equals(b));//比较的是字符数组 System.out.println(a==b.intern());
输出结果
false
true
true - 其他方法
char charAt(int index) //返回字符串的第index个字母,index从0开始 String concat(String str) //返回拼接后的字符串 ,完成数组复制的过程 int compareTo(String anotherString) //比较两个字符串大小 int compareToIgnoreCase(String str) //比较两个字符串大小,忽略大小写,都转成小写 boolean contains(CharSequence s) //是否包含字符串 int indexOf(int ch)//搜索第一个出现的字符ch的下标 int indexOf(String str) //搜索第一个出现的字符串str的下标 int lastIndexOf(int ch) //搜索最后一个出现的字符ch的位置 int lastIndexOf(String value) //搜索最后一个出现的字符串value的位置 int lastIndexOf(int ch, int fromIndex) //从某个未知开始,查找某个字符串,返回字符串的起始位置 int length() //返回字符串的长度 String replace(char oldChar, char newChar) //返回一个新串,它是通过用newChar 替换此字符串中出现的所有oldChar而生成的 boolean startsWith(String prefix) //如果字符串以prefix开始,则返回true boolean endsWith(String prefix) //如果字符串以prefix结尾,则返回true String substring(int beginIndex) //提取从位置索引开始的字符串部分 String substring(int beginIndex,int endIndex) //返回一个新字符串,该串包含从原始字符串beginIndex到串尾戒endIndex-1的所有字符,左闭右开 String toLowerCase() //返回一个新字符串,该串将原始字符串中的所有大写字母改成小写字母 String toUpperCase() //返回一个新字符串,该串将原始字符串中的所有小写字母改成大写字母 String trim() //返回一个新字符串,该串删除了原始字符串头部和尾部的空格
二、可变字符序列——StringBuffer(final类)(线程安全;效率低)
StringBuffer stringBuffer=new StringBuffer();
stringBuffer.append(1).append(1.234).append("abc").append(true).append("adkfddlfkjdf");
String str=stringBuffer.toString();
System.out.println(stringBuffer);
System.out.println(stringBuffer.length());
System.out.println(stringBuffer.capacity());
System.out.println(stringBuffer.substring(2,6));
System.out.println(stringBuffer.charAt(3));
三、可变字符序列——StringBuilderf(final类)(线程不安全;效率高 )
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("123").append(false);
System.out.println(stringBuilder);
stringBuilder.insert(2, 66666);
System.out.println(stringBuilder);
System.out.println(stringBuilder.capacity());
System.out.println(stringBuilder.length());