一、 String Stringbuilder Stringbuffer简介
1.1 String
字符串常量,字符串长度不可变(immutable)
String 类源码(截取常用方法和属性)
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash; // Default to 0
public String() {
this.value = "".value;
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
public int length() {
return value.length;
}
public boolean isEmpty() {
return value.length == 0;
}
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
//判断字符串是否已prefix为开头
public boolean startsWith(String prefix) {
return startsWith(prefix, 0);
}
//判断字符串是否以suffix为结尾
public boolean endsWith(String suffix) {
return startsWith(suffix, value.length - suffix.value.length);
}
//根据字符串开始下标截取
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
//根据开始和结束下标截取字符串的部分
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
public String toString() {
return this;
}
//将字符串的大写字母换为小写
public String toLowerCase() {
return toLowerCase(Locale.getDefault());
}
//将字符串的小写字母转为大写
public String toUpperCase() {
return toUpperCase(Locale.getDefault());
}
// 去除字符串前后空格
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
}
1.2 StringBuffer
字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 StringBuffer,转成 String 类型,调用 StringBuffer 的 toString() 方法即可。
主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。其中append 方法始终将这些字符添加到缓冲区的末端;insert 方法则在指定的点添加字符。
StringBuffer 类源码(截取部分常用的属性和方法)
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
private transient char[] toStringCache;
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
public synchronized StringBuffer append(StringBuffer sb) {
toStringCache = null;
super.append(sb);
return this;
}
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
toStringCache = null;
super.replace(start, end, str);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, String str) {
toStringCache = null;
super.insert(offset, str);
return this;
}
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}
@Override
public synchronized String substring(int start) {
return substring(start, count);
}
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
}
1.3 StringBuilder
StringBuilder 类源码(截取部分常用的属性和方法)
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
}
1.4 三者区别
String 类型和 StringBuffer 的主要性能区别:String 是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。
使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
二、编程题(来自牛客网)
2.1 字符串变形
对于一个长度为 n 字符串,我们需要对它做一些变换。首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把这个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。比如"Hello World"变形后就变成了 “wORLD hELLO”。
如输入:"This is a sample",16
输出:"SAMPLE A IS tHIS"
思路分析:字符串需要变化多次,使用StringBuffer存储,使用到StringBuffer的append()添加,reverse()反转,substring()截取,toString()转为String和replace()代替。代码程序步骤如下:
1,反转大小写
2,反序字符串,根据空格再次反序单词
public class Solution {
public String trans(String s, int n) {
if(n == 0)
return s;
// write code here
StringBuffer result = new StringBuffer();
//1.反转大小写
for(int i=0; i<n; i++){
if(s.charAt(i) >= 'a' && s.charAt(i) <= 'z'){
//小写字母换为大写
result.append((char)(s.charAt(i) - 'a' + 'A'));
}else if(s.charAt(i) >= 'A' && s.charAt(i) <= 'Z'){
//大写字母换为小写
result.append((char)(s.charAt(i)- 'A' + 'a'));
}else{
//其它字符直接写入
result.append(s.charAt(i));
}
}
//2.反序字符串,根据空格二次反序单词
result = result.reverse(); //第一次反序
for(int i=0; i<n; i++){
int in1 = i;
//根据空格再次反序 并替换
while(i<n && result.charAt(i) != ' ')
i++;
StringBuffer temp = new StringBuffer(result.substring(in1, i));
result.replace(in1, i, temp.reverse().toString());
}
return result.toString();
}
}