1. 继承关系图
当使用文本数据时,Java提供了三种类别,包括String, StringBuffer和StringBuilder。当使用大数据来工作时,你应该用StringBuffer或StringBuilder来优化效率。基本上这三个类有许多相似之处。
- String 是不可变的(这个概念的更多详细信息,在文档中)。它不允许子类的存在。
- StringBuffer, StringBuilder 是可变的。
StringBuilder和StringBuffer都是一样的,除了涉及到多线程的使用情况。
- 为了处理多线程使用文本,你应该为了防止线程之间冲突而使用StringBuffer。
- 要使用一个线程处理的文本,你应该使用StringBuilder。
至于处理的速度,StringBuilder是最好的,其次是StringBuffer,而最后是String。
2. String类型
String 在Java中是最重要的一个类,Java编程开始使用字符串就使用著名的System.out.println()语句在控制台上打印东西。许多Java初学者不知道String是不可变的和最终的Java字符串结果,每次修改需要创建一个新的String对象。
2.1- String是一个非常特殊的类
字符串接受Java的特殊处理,因为它们在程序中经常使用。因此,效率(在计算和存储方面)是至关重要的。
Java的设计者决定这一个面向对象语言,以保留原始类型,而不是使所有的对象, 以便提高语言的性能。原始数据存储(在)调用栈,其需要较少的存储空间和更方便的操作。另一方面,对象被存储在程序堆,这需要复杂的存储器管理和更多的存储空间。出于性能的原因,Java字符串被设计为在一种原始和类之间类型。特殊功能的字符串包括:
“+”操作符,它执行的加入对原始类型(如int和double),重载对String对象进行操作。’+’两个字符串操作数进行串联。 Java不考虑让开发者支持运算符重载。在支持运算符重载像C++语言,可以把一个“+”操作符来执行减法,引起不良代码。 “+”操作符是重载的内部支持字符串连接在Java中的唯一操作符。注意到,“+”不在两个任意对象上工作。
一个字符串,可以通过构造:
直接分配字符串到字符串引用 - 就像一个原始数据类型或通过“new”操作符和构造,类似于任何其他类。然而,这是不常用的,所以不推荐。字符串字面存储在一个公共池。这有利于对具有相同内容的字符串,以节省存储存储的共享。new操作符分配的String对象都存储在堆中,并没有对相同内容的共享存储。
2.2 String文字和String对象
正如前面提到的,有两种方法来构造字符串:通过指定一个字符串字面量或显式创建通过 new 操作符,并构造一个String对象的隐式构建。 例如,
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
我们使用以下图片说明来解释它:
Java已经提供了一个特殊的机制,来保存字符串文字 - 所谓的字符串公共池。如果两个字符串具有相同的内容,它们将共享公共池内同一存储器。这样的做法是采取以节省对经常使用的字符串存储。在另一方面,通过 new 操作符和构造器创建String对象都保存在堆中。 在堆中的每个String对象都有自己的存储就像任何其他对象。没有共享存储堆,即使两个String对象具有相同的内容。
可以使用String类的方法equals()方法比较两个字符串的内容。可以使用关系等于运算符’==’来比较两个对象的引用(或指针)。研究以下代码:
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
s1 == s1; // true, same pointer
s1 == s2; // true, s1 and s2 share storage in common pool
s1 == s3; // true, s3 is assigned same pointer as s1
s1 == s4; // false, different pointers
s4 == s5; // false, different pointers in heap
s1.equals(s3); // true, same contents
s1.equals(s4); // true, same contents
s4.equals(s5); // true, same contents
事实上,你应该使用字符串,而是采用了“new”的操作符,这有助于加快程序运行速度。
3. StringBuffer 和 StringBuilder
StringBuffer是可变的。它可以在长度和内容方面发生变化。StringBuffer是线程安全的,这意味着它们已经同步方法来控制访问,以便只有一个线程可以在同一时间访问一个StringBuffer对象同步代码。因此,StringBuffer的对象通常在多线程环境中是安全的,使用多个线程可以试图同时访问相同StringBuffer对象。
StringBuilder类非常相似的StringBuffer,不同之处在于它的访问不同步的,因此,它不是线程安全的。由于不同步,StringBuilder的性能可以比StringBuffer更好。因此,如果在单线程环境中工作,使用StringBuilder,而不是StringBuffer可能会有更高的性能。这也类似其他情况,如StringBuilder的局部变量(即一个方法中的一个变量),其中只有一个线程会访问一个StringBuilder对象。
StringBuffer的方法(StringBuilder相似)
// Constructors
StringBuffer() // an initially-empty StringBuffer
StringBuffer(int size) // with the specified initial size
StringBuffer(String s) // with the specified initial content
// Length
int length()
// Methods for building up the content
// type could be primitives, char[], String, StringBuffer, etc
StringBuffer append(type arg) // ==> note above!
StringBuffer insert(int offset, type arg) // ==> note above!
// Methods for manipulating the content
StringBuffer delete(int start, int end)
StringBuffer deleteCharAt(int index)
void setLength(int newSize)
void setCharAt(int index, char newChar)
StringBuffer replace(int start, int end, String s)
StringBuffer reverse()
// Methods for extracting whole/part of the content
char charAt(int index)
String substring(int start)
String substring(int start, int end)
String toString()
// Methods for searching
int indexOf(String searchKey)
int indexOf(String searchKey, int fromIndex)
int lastIndexOf(String searchKey)
int lastIndexOf(String searchKey, int fromIndex)
- StringBuilderDemo.java
package com.yiibai.tutorial.strbb;
public class StringBuilderDemo {
public static void main(String[] args) {
// Create StringBuilder object
// with no characters in it and
// an initial capacity specified by the capacity argument
StringBuilder sb = new StringBuilder(10);
// Append the string Hello ... on sb.
sb.append("Hello...");
System.out.println("- sb after appends a string: " + sb);
// append a character
char c = '!';
sb.append(c);
System.out.println("- sb after appending a char: " + sb);
// Insert a string at index 5
sb.insert(8, " Java");
System.out.println("- sb after insert string: " + sb);
// Delete substring at index 5 to 8
sb.delete(5,8);
System.out.println("- sb after delete: " + sb);
}
}
运行示例的结果:
- sb after appends a string: Hello...
- sb after appending a char: Hello...!
- sb after insert string: Hello... Java!
- sb after delete: Hello Java!