java String, StringBuffer,StringBuilder
来源:互联网 发布:领淘宝内部优惠券软件 编辑:程序博客网 时间:2024/05/21 06:16
面试题: String,StringBuffer,StringBuilder的区别?
1:String是不可改变的量,声明的内容不可以修改,而StringBuffer和StringBuilder都是可变字符串序列,声明的内容可以修改;
2:StringBuffer是同步方法,属于线程安全操作,StringBulder是异步方法,属于非线程安全操作;
使用场景:
使用 String 类的场景:在字符串不经常变化的场景中可以使用 String 类,例如常量的声明、少量的变量运算。
使用 StringBuffer 类的场景:在频繁进行字符串运算(如拼接、替换、删除等),并且运行在多线程环境中,则可以考虑使用 StringBuffer,例如 XML 解析、HTTP 参数解析和封装。
使用 StringBuilder 类的场景:在频繁进行字符串运算(如拼接、替换、和删除等),并且运行在单线程的环境中,则可以考虑使用 StringBuilder,如 SQL 语句的拼装、JSON 封装等。
分析:
在性能方面,由于 String 类的操作是产生新的 String 对象,而 StringBuilder 和 StringBuffer 只是一个字符数组的扩容而已,所以 String 类的操作要远慢于 StringBuffer 和 StringBuilder。
简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
1: String S1 = “This is only a" + “ simple" + “ test";2: StringBuffer Sb = new StringBuilder(“This is only a").append(“ simple").append(“ test");
你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个
String S1 = “This is only a" + “ simple" + “test";
源码:
String,StringBuffer,StringBuilder都实现了CharSequence接口。
public interface CharSequence{int length();// return the char value at the specified indexchar charAt(int index);// return a new CharSequence that is a subsequence// of this sequence.CharSequence subSequence(int start, int end);public String toString();}
String的源码
public final class String{private final char value[]; // used for character storageprivate int the hash; // cache the hash code for the string}
成员变量只有两个:
final的char类型数组
int类型的hashcode
构造函数
public String()public String(String original){this.value = original.value;this.hash = original.hash; }public String(char value[]){ this.value = Arrays.copyOf(value, value.length); }public String(char value[], int offset, int count){// 判断offset,count,offset+count是否越界之后this.value = Arrays.copyOfRange(value, offset, offset+count);}
这里用到了一些工具函数
copyOf(source[],length); 从源数组的0位置拷贝length个;
这个函数是用System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength))实现的。
copyOfRange(T[] original, int from, int to)。
构造函数还可以用StringBuffer/StringBuilder类型初始化String,
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());}
除了构造方法,String类的方法有很多,
length,isEmpty,可以通过操作value.length来实现。
charAt(int index):
通过操作value数组得到。注意先判断index的边界条件
public char charAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; }
getChars方法
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { \\边界检测 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
equals方法,根据语义相等(内容相等,而非指向同一块内存),重新定义了equals
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;}
如果比较的双方指向同一块内存,自然相等;(比较==即可)
如果内容相等,也相等,比较方法如下:
首先anObject得是String类型(用关键字instanceof)
然后再比较长度是否相等;
如果长度相等,则挨个元素进行比较,如果每个都相等,则返回true.
还有现成安全的与StringBuffer内容比较
contentEquals(StringBuffer sb),实现是在sb上使用同步。
compareTo():
如果A大于B,则返回大于0的数;
A小于B,则返回小于0的数;
A=B,则返回0
public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2;}
regionMatches:如果两个字符串的区域都是平等的,
public boolean regionMatches(int toffset, String other, int ooffset, int len) {//判断边界条件 while (len-- > 0) { if (ta[to++] != pa[po++]) { return false; } } }public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) { while (len-- > 0) { char c1 = ta[to++]; char c2 = pa[po++]; if (c1 == c2) { continue; } if (ignoreCase) { // If characters don't match but case may be ignored, // try converting both characters to uppercase. // If the results match, then the comparison scan should // continue. char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) { continue; } // Unfortunately, conversion to uppercase does not work properly // for the Georgian alphabet, which has strange rules about case // conversion. So we need to make one last check before // exiting. if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { continue; } } return false; } return true; }
startsWith(String prefix, int toffset)
startsWith(String prefix)
endsWith(String suffix)
{return startsWith(suffix, value.length - suffix.value.length); }
substring(int beginIndex,int endIndex)
除了条件判断:
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
字符串连接concat(String str)
int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true);
对于StringBuffer和StringBuilder StringBuffer 和 StringBuilder 都是继承于 AbstractStringBuilder, 底层的逻辑(比如append)都包含在这个类中。
public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len);//查看使用空间满足,不满足扩展空间 str.getChars(0, len, value, count);//getChars就是利用native的array copy,性能高效 count += len; return this;}
StringBuffer 底层也是 char[], 数组初始化的时候就定下了大小, 如果不断的 append 肯定有超过数组大小的时候,我们是不是定义一个超大容量的数组,太浪费空间了。就像 ArrayList 的实现,采用动态扩展,每次 append 首先检查容量,容量不够就先扩展,然后复制原数组的内容到扩展以后的数组中.
- Java String,StringBuilder,StringBuffer
- JAVA String StringBuffer Stringbuilder
- Java String\StringBuffer\Stringbuilder
- Java String StringBuilder StringBuffer
- Java String StringBuilder StringBuffer
- Java String StringBuilder StringBuffer
- Java String StringBuilder StringBuffer
- Java String StringBuffer StringBuilder
- JAVA String StringBuffer StringBuilder
- java String、StringBuffer、StringBuilder
- java: String StringBuffer StringBuilder
- java String, StringBuffer,StringBuilder
- java String StringBuffer StringBuilder
- java string stringbuilder stringbuffer
- Java String、StringBuffer、StringBuilder
- java String stringbuilder stringbuffer
- java String StringBuffer Stringbuilder
- Java String StringBuffer StringBuilder
- 几个C/Cpp笔试面试题目
- 【CJOJ P1365】最短路
- Caffe:Message type "caffe.LayerParameter" has no field named "reshape_param".
- Service生命周期
- java---《深入理解java虚拟机》第二章【java内存区域与内存溢出异常】阅读笔记
- java String, StringBuffer,StringBuilder
- 【软考总结】——好事多磨
- ln命令介绍
- Cannot open /var/log/sa/sa23: No such file or directory
- 20、Spring MVC 之 Configuring
- iOS开发中, '-[__NSCFConstantString size]: unrecognized selector sent to instance 0x10abccc00'
- 二叉树的先序后序中序遍历(递归非递归)
- 4、Spring MVC实操
- 30天自制操作系统U盘启动