字符串 vs 字符串缓冲区 vs 字符串构建器

字符串是Java中最广泛使用的类之一。StringBuffer和StringBuilder类提供了操作字符串的方法。我们将探讨StringBuffer和StringBuilder之间的区别。StringBuffer和StringBuilder之间的区别是一个常见的Java面试问题。

字符串 vs 字符串缓冲区 vs 字符串构建器

字符串是核心Java面试中最重要的主题之一。如果你正在编写一个在控制台打印内容的程序,你就会使用字符串。本教程旨在重点讨论字符串类的主要特性。然后,我们将比较StringBuffer和StringBuilder类。

Java中的字符串

    1. String类表示字符字符串,我们可以有两种方式来实例化String。

String str = “ABC”;
// 或者
String str = new String(“ABC”);

在Java中,String是不可变的。所以在多线程环境中使用它是适当的。我们可以在函数之间共享它,因为不存在数据不一致的问题。

当我们使用双引号创建一个String时,JVM首先在字符串池中查找具有相同值的String。如果找到了,它将返回字符串池中字符串对象的引用。否则,它将在字符串池中创建String对象并返回引用。通过在不同的线程中使用相同的String,JVM可以节省大量的内存。

如果使用new运算符创建字符串,它将在堆内存中创建。

+运算符对String进行了重载。我们可以使用它来连接两个字符串。尽管内部实际上使用StringBuffer来执行此操作。

String覆盖了equals()和hashCode()方法。仅当两个字符串具有相同的字符序列时它们才相等。equals()方法区分大小写。如果你需要进行大小写不敏感的检查,应该使用equalsIgnoreCase()方法。

字符串使用UTF-16编码进行字符流处理。

String是一个final类。除了“private int hash”之外,所有字段都是final的。该字段包含hashCode()函数的值。hashcode的值只有在第一次调用hashCode()方法时才会计算,并在该字段中被缓存。此外,hash是使用String类的final字段进行一些计算生成的。因此,每次调用hashCode()方法时,都会得到相同的输出。对于调用者来说,似乎每次都进行计算,但实际上它被缓存在hash字段中。

字符串 vs 字符串缓冲区

由于Java中的String是不可变的,所以无论是进行字符串的连接、子字符串等操作,都会生成一个新的String对象,并丢弃旧的String对象以便进行垃圾回收。这些操作会消耗大量的系统资源并在堆中产生大量的垃圾。为此,Java提供了StringBuffer和StringBuilder类来进行字符串操作。StringBuffer和StringBuilder是可变的对象,在Java中使用它们来进行字符串操作。它们提供了append()、insert()、delete()和substring()等方法。

StringBuffer和StringBuilder的区别

直到Java 1.4之前,StringBuffer是处理字符串操作的唯一选择。然而,它有一个缺点,即其所有公共方法都是同步的。StringBuffer提供了线程安全性,但却降低了性能。在大多数情况下,我们并不需要在多线程环境中使用String。因此,Java 1.5引入了一个新类StringBuilder,它与StringBuffer类似,除了线程安全和同步之外。StringBuffer拥有一些额外的方法,例如substring、length、capacity、trimToSize等。然而,这些方法在String中也都存在,因此在StringBuilder类中没有实现。StringBuffer在Java 1.0中引入,而StringBuilder类在Java 1.5中引入,针对StringBuffer的一些缺点进行了改进。如果您在单线程环境中操作或者不关心线程安全,应该使用StringBuilder。否则,对于需要线程安全操作的情况,请使用StringBuffer。

字符串生成器(StringBuilder)与字符串缓冲区(StringBuffer)的性能对比。

我正在尝试检查由于与一个示例程序中的StringBuffer和StringBuilder对象进行多次append()操作而导致的性能影响。

package com.Olivia.java;

import java.util.GregorianCalendar;

public class TestString {

	public static void main(String[] args) {
		System.gc();
		long start=new GregorianCalendar().getTimeInMillis();
		long startMemory=Runtime.getRuntime().freeMemory();
		StringBuffer sb = new StringBuffer();
		//StringBuilder sb = new StringBuilder();
		for(int i = 0; i<10000000; i++){
			sb.append(":").append(i);
		}
		long end=new GregorianCalendar().getTimeInMillis();
		long endMemory=Runtime.getRuntime().freeMemory();
		System.out.println("Time Taken:"+(end-start));
		System.out.println("Memory used:"+(startMemory-endMemory));
	}
}

我也对StringBuffer对象运行了相同的代码,以检查时间和内存值。我对每个案例执行了5次代码,然后计算了平均值。

Value of i StringBuffer (Time, Memory) StringBuilder (Time, Memory)
10,00,000 808, 149356704 633, 149356704
1,00,00,000 7448, 147783888 6179, 147783888

很明显,在单线程环境中,StringBuilder的性能比StringBuffer要好。这种性能差异可以归因于StringBuffer方法中的同步操作。

字符串 vs. 字符串缓冲区 vs. 字符串生成器

    1. 字符串是不可变的,而StringBuffer和StringBuilder是可变的类。

 

    1. StringBuffer是线程安全且同步的,而StringBuilder不是。这就是为什么StringBuilder比StringBuffer更快的原因。

 

    1. 字符串连接操作符(+)内部使用了StringBuffer或StringBuilder类。

 

    在非多线程环境中进行字符串操作时,应使用StringBuilder;否则使用StringBuffer类。

这就是有关String、StringBuffer和StringBuilder差异的快速总结。在大多数一般的编程场景中,StringBuilder比StringBuffer更适用。参考资料:

  • String API Doc
  • StringBuffer API Doc
  • StringBuilder API Doc
发表回复 0

Your email address will not be published. Required fields are marked *


广告
将在 10 秒后关闭
bannerAds