Java 字符串之 String,StringBuffer,StringBuilder
一:比拟
执行速度:StingBuilder>StringBuffer>String
String 字符串常量
StringBuffer 字符串变量(线程平安)
StringBuilder 字符串变量(线程不平安), 都实现了 CharSequence 接口示意有序的字符汇合
CharSequence 接口有几个办法:
1. 获取指定索引的字符:public char charAt(int index)
2. 获取字符串长度:public int length()
3. 截取局部字符串:public CharSequence subSequence(int start, int end)
4. 转成 String 类型:public String toString()
二:String 字符串类型
Java String 类为什么是 final 的?
1. 为了实现字符串池,2. 为了线程平安,3. 为了实现 String 能够创立 HashCode 不可变性
final 润饰类不能被继承,即它不能领有本人的子类
final 润饰办法不能被重写
final 润饰的变量,无论是类属性,对象属性,形参,还是局部变量,都须要进行初始化操作。
String 类不可变性的益处
1. 只有当字符串是不可变的,字符串池才有可能实现。字符串池的实现能够在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串。
如果字符串是可变的,那么会引起很重大的平安问题。因为字符串是不可变的,所以它的值是不可扭转的,否则扭转字符串指向的对象的值,造成安全漏洞。
2. 因为字符串是不可变的,所以是多线程平安的,同一个字符串实例能够被多个线程共享。这样便不必因为线程平安问题而应用同步。字符串本人便是线程平安的。
类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。譬如你想加载 java.sql.Connection 类,而这个值被改成了 myhacked.Connection,那么会对你的数据库造成不可知的毁坏。
3. 因为字符串是不可变的,所以在它创立的时候 hashcode 就被缓存了,不须要从新计算。这就使得字符串很适宜作为 Map 中的键,字符串的处理速度要快过其它的键对象。这就是 HashMap 中的键往往都应用字符串。
public final class String implements Serializable, Comparable<String>, CharSequence{}
String 的函数表
// 构造函数无参
public String()
public String(String original)
//char 数组类型转成 String
public String(char[] value)
//char 数组类型,起始地位,和总数
public String(char[] value, int offset, int count)
// 字节数组类型
public String(byte[] bytes)
// 字节数组类型, 起始地位,长度
public String(byte[] bytes, int offset, int length)
// 字节数组类型,对应编码
public String(byte[] bytes, String charsetName)
例子:String aa=new String(new byte[]{(byte)0x5b,(byte)0x57},"utf-8");
// 字节数组类型,起始地位,长度,对应编码
public String(byte[] bytes, int offset, int length, String charsetName)
// 字节数组类型,字符对应编码
public String(byte[] bytes, Charset charset)
例子:String aa=new String(new byte[]{(byte)0x5b,(byte)0x57},Charset.forName("gbk"));
// 字节数组类型,起始地位,长度,字符对应编码
public String(byte[] bytes, int offset, int length, Charset charset)
public String(int[] codePoints, int offset, int count)
//StringBuffer 和 StringBuilder 转成 String
public String(StringBuffer buffer)
public String(StringBuilder builder)
// 依据索引获取字符
public char charAt(int index)
public int codePointAt(int index)
public int codePointBefore(int index)
public int codePointCount(int beginIndex, int endIndex)
// 比拟 2 个 String 的大小
public int compareTo(String anotherString)
// 比拟 2 个 String 的大小(疏忽大小写)public int compareToIgnoreCase(String str)
// 字符串前面追加字符串
public String concat(String str)
// 和 StringBuffer 的内容比拟
public boolean contentEquals(StringBuffer sb)
public boolean contentEquals(CharSequence cs)
public static String copyValueOf(char[] data, int offset, int count)
public static String copyValueOf(char[] data)
// 比拟 2 个 String 是否相等
public boolean equals(Object anObject)
// 比拟 2 个 String 是否相等(疏忽大小写)public boolean equalsIgnoreCase(String anotherString)
public static String format(String format, Object[] args)
public static String format(Locale l, String format, Object[] args)
public int hashCode()
// 依据字符查问索引
public int indexOf(int ch)
// 依据字符,字符地位查问索引
public int indexOf(int ch, int fromIndex)
// 依据字符串查问索引
public int indexOf(String str)
// 依据字符串,字符地位查问索引
public int indexOf(String str, int fromIndex)
public String intern()
// 依据字符从后往前查问索引
public int lastIndexOf(int ch)
public int lastIndexOf(int ch, int fromIndex)
// 依据字符串从后往前查问索引
public int lastIndexOf(String str)
public int lastIndexOf(String str, int fromIndex)
// 字符串长度
public int length()
// 匹配字符串
public boolean matches(String regex)
public int offsetByCodePoints(int index, int codePointOffset)
// 2 个字符串比拟开始地位,字符串,完结地位,长度
public boolean regionMatches(int toffset, String other, int ooffset, int len)
// 2 个字符串比拟疏忽大小写,开始地位,字符串,完结地位,长度
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
// 替换字符
public String replace(char oldChar, char newChar)
public String replace(CharSequence target, CharSequence replacement)
// 全副替换
public String replaceAll(String regex, String replacement)
// 替换第一次呈现的字符
public String replaceFirst(String regex, String replacement)
// 宰割字符成字符串数组
public String[] split(String regex, int limit)
public String[] split(String regex)
// 判断结尾字符是不是输出字符,索引地位开始
public boolean startsWith(String prefix, int toffset)
/ 判断结尾字符是不是输出字符
public boolean startsWith(String prefix)
// 判断结尾字符串是不是输出字符
public boolean endsWith(String suffix)
// 判断字符串是不是蕴含 **
public boolean contains(CharSequence s)
public CharSequence subSequence(int beginIndex, int endIndex)
// 截取字符串局部
public String substring(int beginIndex)
public String substring(int beginIndex, int endIndex)
// 转成字符数组
public char[] toCharArray()
// 转成小写
public String toLowerCase(Locale locale)
public String toLowerCase()
// 转成 String
public String toString()
// 转成大写
public String toUpperCase(Locale locale)
public String toUpperCase()
public String trim()
// 把各种对象转成 String
public static String valueOf(Object obj)
public static String valueOf(char[] data)
public static String valueOf(char[] data, int offset, int count)
public static String valueOf(boolean b)
public static String valueOf(char c)
public static String valueOf(int i)
public static String valueOf(long l)
public static String valueOf(float f)
public static String valueOf(double d)
// 获取对应的字符串的字节数组
public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin)
public byte[] getBytes(String charsetName)
public byte[] getBytes(Charset charset)
public byte[] getBytes()
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
public boolean isEmpty()
三:StringBuffer 可变字符串变量
StringBuffer 对象初始化,通常状况下应用构造函数进行初始化。
StringBuffer 的构造函数
无参结构默认调用容量 16 的有参结构
public StringBuffer(){super(16)}
有参结构,容量多少
public StringBuffer(int capacity) {super(capacity);
}
传入字符串结构,容量是字符串长度 +16
public StringBuffer(String str)
相干办法
将制订字符追加到字符序列
1.public StringBuffer append(String s)
// 字符数组增加指定地位字符序列
2.public StringBuffer append(char[] str, int offset, int len)
// 将此字符序列用其反转模式取代
3.public StringBuffer reverse()
// 将 int 参数的字符串示意模式插入此序列中
4.public insert(int offset, int i)
// 移除此序列的子字符串中的字符
5.public delete(int start, int end)
// 应用给定 String 中的字符替换此序列的子字符串中的字符。6.replace(int start, int end, String str)
// 返回以后容量
7.int capacity()
返回此序列中指定索引处的 char 值
8.char charAt(int index)
// 确保容量至多等于指定的最小值
9.void ensureCapacity(int minimumCapacity)
// 将字符从此序列复制到指标字符数组 dst
10.void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
// 返回第一次呈现的指定子字符串在该字符串中的索引
11.int indexOf(String str)
// 返回最左边呈现的指定子字符串在此字符串中的索引
12.int lastIndexOf(String str)
// 将给定索引处的字符设置为 ch
13.void setCharAt(int index, char ch)
// 设置字符序列的长度
14.void setLength(int newLength)
// 返回一个新的字符序列,该字符序列是此序列的子序列
15.CharSequence subSequence(int start, int end)
// 返回一个新的 String,它蕴含此序列以后所蕴含的字符子序列
16.String substring(int start, int end)
StringBuffer,StringBuilder 扩容形式
构造函数中调用 append 办法
public StringBuffer(String str) {super(str.length() + 16);
append(str);
}
append 办法中调用 AbstractStringBuilder 父类的 append 办法
public synchronized StringBuffer append(String str) {super.append(str);
}
父类中 append 办法
public AbstractStringBuilder append(String str) {if (str == null)// 先判断字符串是否为空
return appendNull();
int len = str.length();// 字符串长度
ensureCapacityInternal(count + len);// 此办法判断字符数组 value 的容量是否足够,cout 是字符被应用的容量 + 传进去的字符长度
str.getChars(0, len, value, count);
count += len;
return this;}
跟进去 ensureCapacityInternal 看看
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {//value 默认的长度是 16+ 传入的字符长度
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
a. 如果传进来的参数小于 value 数组的长度,那么阐明容量曾经足够,不须要扩容
b. 如果传进来的参数大于 value 数组的长度,阐明本来设定的容量曾经不够用,须要扩容解决,这里的 Arrays.copyOf(char[] a,int b),就是将 a 这个数组复制到一个 b 长度的新数组中,并返回这个 b 长度的数组,这里的 b 就是 newCapacity(minimumCapacity)
如果数组空间不够传入,newCapactiy()
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;// 新的数组空间左移一位 +2,相当于 * 2 容量 +2
if (newCapacity - minCapacity < 0) {newCapacity = minCapacity;// 相当赋给新的数组}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)// 最大容量 2147483647-8
? hugeCapacity(minCapacity)
: newCapacity;
}
四:StringBuffer 和 StringBuilder 的区别
1.StringBuffer 的继承关系和 StringBuilder 完全一致,因而 StringBuffer 外部也是调用的 AbstractStringBuilder 的办法,所以很多办法的了解都和 StringBuilder 相差无几
2. 但和 StringBuilder 不同的是,StringBuffer 的每个办法上都用了 synchronized 润饰,当波及到多线程调用时 StringBuffer 是线程平安的,与之绝对的 StringBuilder 便线程不平安了,但因而 StringBuilder 的效率要比 StringBuffer 高
3. 所以,当咱们在多线程环境下该当应用 StringBuffer 以保障线程平安,而在单线程环境下应用 StringBuilder 以提高效率