Java之String/StringBuffer/StringBuilder

目录

三者关系

https://blog.csdn.net/jisuanjiguoba/article/details/82531868
https://www.runoob.com/w3cnote/java-different-of-string-stringbuffer-stringbuilder.html
https://www.zhihu.com/question/20101840

  • 快慢关系
    StringBuilder>StringBuffer>String
    为何String最慢呢?因为String是不可变的,所以要修改时(其实就是将String指向了一个新对象,内容是修改的字符串值),涉及到创建和回收对象,所以耗时。具体解释如下:
  • 线程安全与否
    String不可变,所以自然是线程安全
    StringBuffer是线程安全,因为很多方法都由synchronized关键词来修饰
    StringBuilder不是线程安全的
  • 三者相互转换
  1. String vs. StringBuffer (StringBuilder转换类似)
public class StringAndStringBufferSwitch {
    public static void main(String[] args) {        
 
        //String -> StringBuffer
        //创建一个String对象
        String str = "Hi Java!";
        System.out.println(str); 
        //方式一:构造方法
        StringBuffer buffer = new StringBuffer(str);
        System.out.println(buffer); 
        //方式二:通过append方法
        StringBuffer buffer2 = new StringBuffer();
        buffer2.append(str);
        System.out.println(buffer2);

        //StringBuffer -> String
        //创建一个StringBuffer对象
        StringBuffer buffer3 = new StringBuffer();
        buffer3.append("Happy birthday Java!");
        System.out.println(buffer3); 
        //方式一:通过构造方法
        String str2 = new String(buffer3);  
        System.out.println(str2);         
        //方式二:通过toString方法
        String str3 = buffer3.toString();
        System.out.println(str3);
    }
}

String

https://github.com/CyC2018/CS-Notes
https://blog.csdn.net/fly_fly_fly_pig/article/details/82492491

  • 特性
    不可变,final修饰。在java8中,String内部使用char数组;在java9中,使用byte数组
    不可变的好处:适合作map的键值、天生支持多线程、比较安全(比如传送网络地址时)、String pool的需要
  • 关于String的="xxx"和new String("xxx")区别,以及字符串相等的判定,以及intern()函数的使用,见下面的代码解释:
public class TestString {
	public static void main(String[] args) {
		//直接使用="xxx"构造,会自动将“xxx”放入String pool,因此s2构造时,直接指向s1当时构造的“abc”。因此两者hashcode或==都一样
		String s1 = "abc";
		String s2 = "abc";
		System.out.println(s1.equals(s2));
		System.out.println("s1.hashcode: "+s1.hashCode()+"; s2.hashcode: "+s2.hashCode());
		System.out.println(s1 == s2);
		//此时String pool中已有“abc”,因此虽然是使用new String("abc")新建一个对象,但是查找到String pool已有,同样也是指向相同的引用
		String s3 = new String("abc");
		System.out.println("s3.hashcode: "+s3.hashCode());
		//然而,若我们用new String新建两个相同的字符串但是之前未出现在String pool中,则两者的引用不同
		String s4 = new String("xyz");
		String s5 = new String("xyz");
		System.out.println(s4.equals(s5)); //true,因为值相等
		System.out.println("s4.hashcode: "+s4.hashCode()+"; s5.hashcode: "+s5.hashCode());
		System.out.println(s4 == s5);  //不同,因为是两个不同的对象,虽然指向的是同一个地址
		//所以要注意,hashcode相同,也不一定就是同一个对象~
		//使用intern()可手动将字符串放入String pool,这样的话==就为true
		String s6 = s4.intern();
		String s7 = s4.intern();
		System.out.println(s6.equals(s7));
		System.out.println("s6.hashcode: "+s6.hashCode()+"; s7.hashcode: "+s7.hashCode());
		System.out.println(s6 == s7);
		//若使用一个对象作为新new对象的构造函数的参数时,value和hash都相同,但是s7,s8还是不同的对象。。
		String s8 = new String(s7);
		System.out.println(s7.equals(s8));
		System.out.println("s7.hashcode: "+s7.hashCode()+"; s8.hashcode: "+s8.hashCode());
		System.out.println(s7 == s8);
	}
}
result:
true
s1.hashcode: 96354; s2.hashcode: 96354
true
s3.hashcode: 96354
true
s4.hashcode: 119193; s5.hashcode: 119193
false
true
s6.hashcode: 119193; s7.hashcode: 119193
true
true
s7.hashcode: 119193; s8.hashcode: 119193
false

注意:在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。

  • 关于new String("xxx")后的操作
    会生成两个对象,一个是在String pool中生成指向“xxx”的字符串对象,一个是new之后在堆上生成的字符串对象
  • String类方法
    https://www.runoob.com/java/java-string.html

StringBuffer

https://www.runoob.com/java/java-stringbuffer.html

  1. 特殊方法:
public class TestStringBuffer {
	
	public static void main(String[] args) {
		StringBuffer s1 = new StringBuffer("abc");
		System.out.println(s1);
		s1.append("def");
		System.out.println(s1);
		s1.reverse();
		System.out.println(s1);
		s1.delete(1,2); //删除下标为[1,2)的字符
		System.out.println(s1);
		s1.insert(1,1);  //(int offset, int i),将int型的i插入到字符串offset位置,其他字符后移
		System.out.println(s1);
		s1.replace(1,4,"kkk");  //用“kkk”替换掉下标为[1,4)的字符
		System.out.println(s1);
	}
}
result:
abc
abcdef
fedcba
fdcba
f1dcba
fkkkba
  1. 与String同样的方法见https://www.runoob.com/java/java-stringbuffer.html

StringBuilder

StringBuffer 与 StringBuilder 中的方法和功能完全是等价的
https://www.cnblogs.com/onetheway2018/p/11553168.html

posted on 2020-09-18 17:32  pipony  阅读(153)  评论(0)    收藏  举报