常用Java API之String,StringBuffer,StringBuilder类

一, String类

1.1, 创建String对象的方法

//创建一个内容为xiaoming 的字符串
String s1 = "xiaoming";
//创建一个空的字符串
Stinrg s2 = new String();
//创建一个内容为xiaogou的字符串  
String s3 = new String("xiaogou");   
//创建一个内容为char数组的字符串
Sting  s4 = new(char[]{a,b,c})

个别方法的示例代码:

public class StringTest {
    static String str = "JAVA 编程 基础";
    // lastindexof, indexof
    //charAt, length, subString
    // toUpperCase, toLowerCase
    //equals
    public static void main(String[] args) {
        ///last and indexof(ch x) / indexof(string xxxx)
        System.out.println("字符A第一次出现位置"+str.indexOf('A'));
        System.out.println("字符A的最后所在位置"+str.lastIndexOf('A'));

        //charAt(int index)
        System.out.println("给定索引的字符为为"+str.charAt(3));
        //length()
        System.out.println("字符串长度为: "+str.length());
        //substring(int beginIndex)
        System.out.println("输出从第一个A字符索引开始到结束的子字符串: "+ str.substring(1));
        //substring(beginIndex, endindex)
        /// '基'索引为 index=9, 对于substring()要输入到目标索引的下一位
        System.out.println("输出从第一个A字符索引位置到基础的础对应索引位置: "+str.substring(1,10));

        //toUpperCase() ,  toLowerCase()
        System.out.println("输出小写字符串"+str.toLowerCase());

        //equals
    }

输出结果:

subString(startindex,endindex), endindex比实际取到的字符所在的索引多了1位!!!

1.2, String类的常用方法

  • 注意: length在数组中是arr.length, 而在String类中使用的是 stringA.length() !!!

1.3, ==.equals() 的比较

'=='用在引用数据类型(比如字符串)中是比较两个字符串在内存中的地址是否相同, 而用在基本数据类型中是比较值是否相等;
equals 用在字符串中是用于比较字符串字面量是否一致;

  • Object类中定义的equals方法初始行为是比较对象的内存地址,但是在String,Integer,Date这些类中被重写,用来比较字符串的内容.
    示例代码:
public class StrCompare {
    public static void main(String[] args) {
        // == && .equals()
        // ==是字符串比较地址, 而equals是字符串比较内容是否一致
        String str1 = "sb";
        String str2 = "sb";

        String str3 = new String("sb");
        String str4 = new String("sb");

        System.out.println("str1与str2 地址相同吗 ? --" + (str1 == str2));
        System.out.println("str1与str2 内容相同吗? --" + (str1.equals(str2)));

        System.out.println("str1与str3 内容相同吗? --" + (str1.equals(str2)));
        System.out.println("str1 与str3 地址相同吗? --" + (str1 == str3));

        System.out.println("str3 与 str4 地址相同吗? -- " + (str3 == str4));
    }
}

执行结果:

  • 上面示例在内存中的体现:

插个嘴: compareTo()方法, 用于比较同一数据类型的数! 返回值为 1(大于), -1(小于) ,0(等于)
compareTo()详细说明

1.4, String类型变量及对象在内存中的体现总结:(待理清思路)

在Java的实现中,new出来的String对象一般是放在堆中的。
如果是 String s =“xxx”; 这种,那就是放在常量池中.

JDK6将常量池放在方法区中。方法区此时也是持久代。
但是从JDK7开始, 常量池的实现 已经从方法区中移出来放到堆内存里面了。

  • 示例图如下:
  • 总结如下:

  • 来个牛客网的题目:

String类的不可变性:
java规定不能修改字符串中的字符,所以Java里将String类对象称为不可变字符串,例“Hello”永远包含字符H、e、l、l、和o的代码单元序列,不能修改其中的任何一个字符;但是字符串变量是可以修改的,java通过修改String变量的引用位置来修改字符字面量.

  • 答案: true, false
  • 解答: 为什么 a==MESSAGE为ture, 因为a变量拼接后的值跟MESSAGE的值一致,所以编译器会把a的引用指向与MESSAGE引用指向一致的地址; 而对于 (b+c)==MESSAGE为false是因为编译器在编译期间无法确定b和c的值,只有在运行时才会确定是什么字符串.

二, String, StringBuilder 和 StringBuffer(着重记忆)

2.1 引子

由于字符串是常量,其内容和长度都是不变的,如果需要对一个字符串进行修改,则只能创建新的字符串. 为了便于对字符串进行修改,JDK中提供了一个StringBuffer类.

  • 举个栗子:

2.2 总结 (两个sb的具体使用)(▷)

  1. String和StringBuffer(或StringBuilder)
  • String类表示的字符串是常量,一旦创建后,内容和长度是无法修改的,任何对String的改变都会使得新的String引用地址的改变; Stringbuffer表示子符容器,内容和长度可以随时修改; 在操作字符串时,如果该字符串仅用于表示数据类型,用String类即可. 但是如果需要对字符串中的字符进行增删改操作,则使用StringBuffer类;
  • String类重写了Object 的equals方法, 而StringBuffer类没有;
  • String类对象可以使用操作符’+'进行拼接,StringBuffer类对象之间不能;
  1. StringBuffer和StringBuilder的辨析:

StringBuffer和StringBuilder的原理和操作基本相同,
区别在于:

  • StringBufferd支持并发操作,线性安全的,适合多线程中使用
  • StringBuilder不支持并发操作,线性不安全不适合多线程中使用
  • 新引入的StringBuilder类虽然很多不如StringBuffer,但其在单线程中的性能比StringBuffer高

2.3 代码示例

public class StringTest {
 
	public static String BASEINFO = "Mr.Y";
	public static final int COUNT = 2000000;
 
	/**
	 * 执行一项String赋值测试
	 */
	public static void doStringTest() {
 
		String str = new String(BASEINFO);
		long starttime = System.currentTimeMillis();
		for (int i = 0; i < COUNT / 100; i++) {
			str = str + "miss";
		}
		long endtime = System.currentTimeMillis();
		System.out.println((endtime - starttime)
				+ " millis has costed when used String.");
	}
 

 
	/**
	 * 执行一项StringBuilder赋值测试
	 */
	public static void doStringBuilderTest() {
 
		StringBuilder sb = new StringBuilder(BASEINFO);
		long starttime = System.currentTimeMillis();
		for (int i = 0; i < COUNT; i++) {
			sb = sb.append("miss");
		}
		long endtime = System.currentTimeMillis();
		System.out.println((endtime - starttime)
				+ " millis has costed when used StringBuilder.");
	}
 
	
	/**
	 * 测试StringBuilder迭代赋值结果
	 * 
	 * @param mlist
	 */
	public static void doStringBuilderListTest(List<String> mlist) {
		StringBuilder sb = new StringBuilder();
		long starttime = System.currentTimeMillis();
		for (Iterator<String> iterator = mlist.iterator(); iterator.hasNext();) {
			sb.append(iterator.next());
		}
 
		long endtime = System.currentTimeMillis();
		System.out.println(sb.toString() + "builder cost:"
				+ (endtime - starttime) + " millis");
	}
 
	public static void main(String[] args) {
		doStringTest();
		doStringBufferTest();
		doStringBuilderTest();
 
		List<String> list = new ArrayList<String>();
		list.add(" I ");
		list.add(" like ");
		list.add(" BeiJing ");
		list.add(" tian ");
		list.add(" an ");
		list.add(" men ");
		list.add(" . ");
 
		doStringBufferListTest(list);
		doStringBuilderListTest(list);
	}
 
}

执行结果:
2711 millis has costed when used String.
211 millis has costed when used StringBuffer.
141 millis has costed when used StringBuilder.
I like BeiJing tian an men . buffer cost:1 millis
I like BeiJing tian an men . builder cost:0 millis

从上面的结果可以看出,不考虑多线程,采用String对象时(我把Count/100),执行时间比其他两个都要高,而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显。

从后面List的测试结果可以看出,除了对多线程的支持不一样外,这两个类的使用方式和结果几乎没有任何差别,
上面的结果可以看出,不考虑多线程,采用String对象时(我把Count/100),执行时间比其他两个都要高,而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显。由此可见,如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;如果要保证线程安全,自然是StringBuffer

从后面List的测试结果可以看出,除了对多线程的支持不一样外,这两个类的使用方式和结果几乎没有任何差别,

代码摘自: https://blog.csdn.net/mad1989/article/details/26389541
在这里插入图片描述

posted @ 2022-05-26 20:31  青松城  阅读(52)  评论(0)    收藏  举报