StringBuffer和StringBuilder
- 两者实际上是 字符串缓冲区(就是个动态扩容的数组而已!)
- 如果说String是固定长度的且不能修改内容的字符串
- SB就是长度可变的且能够修改内容的字符串
- StringBuffer和StringBuilder 方法都是一样的
- 唯一的区别就在于适用的场景不同,StringBuffer适用于多线程 StringBuilder适用于单线程
- StringBuilder是线程不安全的->没加锁(同步锁) 单 效率会更高
- StringBuffer是线程安全的->加锁(同步锁) 多 效率会更低
- 虽然SB从名字上来看和String有关系 但是不是 SB是另起炉灶的字符串
- String和SB本质上都是字符数组
- String中不支持字符数组扩容和修改内容的
- SB中支持字符数组扩容和修改内容的
StringBuffer和StringBuilder继承类和实现的接口
AbstractStringBuilder(两者的实现父类)
|implement Appendable 可扩展(字符/字符序列)的
Appendable append(char c)
Appendable append(CharSequence csq) //字符序列(字符数组)
Appendable append(CharSequence csq, int start, int end)
|implement CharSequence 此接口对许多不同种类的 char 序列提供统一的只读访问
char charAt(int index)
int length()
CharSequence subSequence(int start, int end)
String toString()
|StringBuilder 有final表示不能被继承 成员函数没有synchronized修饰 无同步锁
|impl Serializable
|impl CharSequence
|StringBuffer 有final表示不能被继承 成员函数都有synchronized修饰 同步锁
|impl Serializable
|impl CharSequence
常用函数
package com.part3字符缓冲区;
import java.util.Arrays;
import com.part1.Person;
public class StringBufferDemo {
public static void main(String[] args) {
StringBuffer s1= new StringBuffer();
StringBuilder s2= new StringBuilder();
String s3 = new String();
char[] c={'1','2','g','j'};
double b=3.54;
s1.append("日本是一个岛国国家");
String s="我爱中国";
s2.append(10);//将 int 参数的字符串表示形式追加到此序列。
s2.append(new Person("老李", 23));//追加 Object 参数的字符串表示形式。其实就是将对象初始化信息添加进去
System.out.println(s2.toString());
s2.append(false);//将 boolean 参数的字符串表示形式追加到序列。
System.out.println(s2.toString());
System.out.println(s2.capacity());//返回当前s2对象的容量 返回当前容量。
System.out.println(s2.append(c, 0, 3));//指定子串的有效返回序列。起坐标和,末位坐标将 char 数组参数的子数组的字符串表示形式追加到此序列。
System.out.println(s2.length());//当前动态数组中的有效字符个数
System.out.println(s2.append(c).toString());//将 char 参数的字符串表示形式追加到此序列。
System.out.println(s2.append(b).toString());//将 double 参数的字符串表示形式追加到此序列。|将 float 参数的字符串表示形式追加到此序列。|追加 Object 参数的字符串表示形式。
System.out.println(s2.append(s).toString());//将指定的字符串追加到此字符序列。
System.out.println(s2.append(s1).toString());//将指定的 StringBuffer 追加到此序列中。
System.out.println(s2.charAt(5));
System.out.println(s2.charAt(4));//返回此序列中指定索引处的 char 值
System.out.println(s2.delete(0, 4));//移除此序列的子字符串中的字符。
System.out.println(s2.deleteCharAt(0));//移除此序列指定位置的 char。
s2.ensureCapacity(10);//确保容量至少等于指定的最小值。
System.out.println(s2.append(105));
System.out.println(s2.indexOf("日"));//返回第一次出现的指定子字符串在该字符串中的索引
System.out.println(s2.indexOf("1",27));//从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。
System.out.println(s2.insert(0, true));//从指定位置开始插入boolean类型值
System.out.println(s2.insert(0, 'l'));//将 char 参数的字符串表示形式插入此序列中。
System.out.println(s2.reverse());
int[] arr={1,2,3,4,5,6,7,8,9,10};
System.out.println(arrayToString(arr));
System.out.println(Arrays.toString(arr));
}
public static String arrayToString(int[] arr){
if(arr==null){
return null;
}
StringBuffer ss = new StringBuffer();
ss.append("[");
for(int i=0;i<arr.length;i++){
ss.append(arr[i]);
if(i==arr.length-1){
return ss.append(']').toString();
}
ss.append(',');
}
return null;
}
}
String类
实际上是一个字符串类,java中存在一个字符串类就是String类。它存储的字符数组不支持扩容和内容修改。
用法:
package part03.StringBuffer与StringBuilder; public class StringDemo { public static void main(String[] args) { /* 此处的 String s1="abc"; String s2="abc"; 可以将s1和s2理解为基本数据类型的变量 "abc"可以理解为基本数据类型的常量 所以 s1 和 s2 这两个变量所存储的都是 "abc"在常量池中的地址 常量池(字符串常量池 StringTable) */ String s1="abc"; String s2="abc"; System.out.println(s1==s2); //true System.out.println(s1.equals(s2)); //true System.out.println("========"); //s3 s4 存的是对象的地址 String s3=new String("abc"); System.out.println(s1==s3); //false System.out.println(s1.equals(s3)); //true System.out.println("========"); String s4=new String("abc"); System.out.println(s3==s4); //false System.out.println(s3.equals(s4)); //true //我们对字符串本身不能进行修改 所以想要扩展字符串内容的话 只能重新创建一个字符串常量出来 //出现一个问题 就是临时字符串的问题 就是下文的 "haha" //临时的字符串越多 也就意味着 字符串常量池中 没有被引用的字符串越多 垃圾越多! //如何优化?如何解决? String s5=s1+"haha"; System.out.println(s1==s5); } }
String和StringBuffer类和StringBuilder区别
字符串缓冲区SB其实就是个动态扩容的数组而已!
如果扩容的次数越多,那么也就意味着所用过的数组也越多 产生的垃圾越多!
我们在使用String去操作的话,也会产生许多临时的字符串 产生的垃圾也多!
咋整?
SB产生的垃圾主要集中在 堆内存
String产生的垃圾主要集中在 方法区(字符串常量池)
【JVM告诉你,GC在堆内存中活跃程度 比在方法区的活跃程度 要大的大的大的多!】
【GC 垃圾收集器】
【也就意味着 GC在堆内存中回收垃圾的效率要远远比在方法区高】
(堆垃圾就像是家用垃圾桶,满了就清理)
(方法区就像是垃圾场,满了才清理)
【堆的垃圾被回收的很快 方法区的垃圾回收的很慢】
综上而言 还是推荐使用SB
基本数据类型包装类
所以我们的基本数据类型其实也有其针对的类描述
byte - Byte
short - Short
int - Integer
long - Long
float - Float
double - Double
char - Character
boolean - Boolean
相关父类
Number
|-- Byte Short Integer Long Float Double 【BigDecimal BigInteger】
Object
|-- Character Boolean
相关操作函数
package part02.基本数据类型包装类;
import java.net.Inet4Address;
public class NumberDemo01 {
public static void main(String[] args) {
Byte b=new Byte("10");
Short s=new Short("10");
Integer i1=new Integer(10); //10
Integer i2=new Integer("10"); //10
Long l=new Long("10");
Float f=new Float("10");
Double d=new Double("10");
Character c=new Character('a');
Boolean bool=new Boolean("true");
//成员函数
System.out.println(i1.compareTo(i2));
System.out.println(i1<i2); //【注意!】
System.out.println(i1+i2);
System.out.println(i1.equals(i2));
System.out.println(i1==i2);
System.out.println(i1.intValue()==i2.intValue());
System.out.println(i1.toString());//将包装类型->字符串 等效于 10+""
//静态函数
System.out.println(Integer.parseInt("123")+1); //默认以十进制解析字符串
System.out.println(Integer.parseInt("10010101",2)); //以二进制解析字符串
//java.lang.NumberFormatException
// System.out.println(Integer.parseInt("10010102",2)); //以二进制解析字符串
System.out.println(Integer.parseInt("102201012",3));//以三进制解析字符串
//最高支持几进制?radix ∈ [2,36] 10个数字+26个字母
System.out.println(Integer.parseInt("123123",36));
System.out.println(Integer.reverse(123));//不是我们简单认为的123-321
System.out.println(Integer.toBinaryString(149));
System.out.println(Integer.toOctalString(149));
System.out.println(Integer.toHexString(149));
System.out.println(Integer.toString(149)); //不是Object重写来的
//静态工厂模式
System.out.println(Integer.valueOf(10)); //等效于 new Integer(10)
/*
Character 当中最常用的就是判断字符的类型相关的函数
自行下去查API
*/
}
}