Java 字符串之String,StringBuffer,StringBuilder

Java 字符串之String,StringBuffer,StringBuilder

一:比较
执行速度:StingBuilder>StringBuffer>String
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(线程不安全),都实现了CharSequence接口表示有序的字符集合
image.png
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, 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以提高效率

你可能感兴趣的:(javaandroid)