为什么会有这种性能差异
why is that performance diffrence
import java.util.Calendar;
public class MainClass
{
public static void main(String args[])
{
String s = new String("ABCD");
long swapStart = Calendar.getInstance().getTimeInMillis();
for(int i=0; i<s.length()/2;i++)
{
char left = s.charAt(i);
char right = s.charAt(s.length()-(i+1));
s=s.substring(0, i)+right+s.substring(i+1, s.length()-(i+1))+left+s.substring(s.length()-i, s.length());
}
long swapStop = Calendar.getInstance().getTimeInMillis();
long bufStart = Calendar.getInstance().getTimeInMillis();
String str = new String("ABCD");
StringBuffer strBuf = new StringBuffer(str);
str = strBuf.reverse().toString();
long bufStop = Calendar.getInstance().getTimeInMillis();
System.out.println(swapStop-swapStart);
System.out.println(bufStop-bufStart);
}
}
***** 在字符串的新字符串 ("ABCD") 中,如果我提供一个非常大的字符串,比如说几百个字母数字
*****在控制台输出是:
61
0
***** 字符串缓冲区始终以 0 毫秒计算,我的字符交换算法根据字符串大小进行计算
问。为什么我的交换算法不能在 0 毫秒内完成,为什么 stringbuffer 总是在 0 毫秒内完成?
我检查了 Java 源代码, StringBuffer.reverse() 实现如下:
public AbstractStringBuilder reverse() {
boolean hasSurrogate = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; --j) {
char temp = value[j];
char temp2 = value[n - j];
if (!hasSurrogate) {
hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
|| (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
}
value[j] = temp2;
value[n - j] = temp;
}
if (hasSurrogate) {
// Reverse back all valid surrogate pairs
for (int i = 0; i < count - 1; i++) {
char c2 = value[i];
if (Character.isLowSurrogate(c2)) {
char c1 = value[i + 1];
if (Character.isHighSurrogate(c1)) {
value[i++] = c1;
value[i] = c2;
}
}
}
}
return this;
}
问。请解释代理人的事情。
Q1:存在性能差异,因为您的交换代码创建了很多要操作的 String
对象,而另一个例程直接使用 char 数组并且不需要创建额外的对象。让我们检查一下您的代码行:
s=s.substring(0, i)+right+s.substring(i+1, s.length()-(i+1))+left+s.substring(s.length()-i, s.length());
它做这样的工作:
s = [new String 1] + char + [new String 2] + char + [new String 3]
这是 4 个新的 String
对象(显示的三个对象,加上添加 String
个对象后产生的对象。此外,显示的 3 个新字符串中的每一个都调用了 substring处理时间。此外,您在 for 循环中完成所有这些工作,因此它会针对每个字符重复!
字符串操作方便但昂贵。数组操作是直接的,不需要额外的对象或内存块,因此速度要快得多。
Q2:代理是 unicode 字符的一种特殊情况,创建它是为了处理更长的 unicode 字符。有关详细信息,请参阅 this article。代理项的 hi/low 部分的顺序很重要,因此交换代码将这两个字符颠倒是错误的,因此如果找到它们,它们的顺序将按原样放回去。
import java.util.Calendar;
public class MainClass
{
public static void main(String args[])
{
String s = new String("ABCD");
long swapStart = Calendar.getInstance().getTimeInMillis();
for(int i=0; i<s.length()/2;i++)
{
char left = s.charAt(i);
char right = s.charAt(s.length()-(i+1));
s=s.substring(0, i)+right+s.substring(i+1, s.length()-(i+1))+left+s.substring(s.length()-i, s.length());
}
long swapStop = Calendar.getInstance().getTimeInMillis();
long bufStart = Calendar.getInstance().getTimeInMillis();
String str = new String("ABCD");
StringBuffer strBuf = new StringBuffer(str);
str = strBuf.reverse().toString();
long bufStop = Calendar.getInstance().getTimeInMillis();
System.out.println(swapStop-swapStart);
System.out.println(bufStop-bufStart);
}
}
***** 在字符串的新字符串 ("ABCD") 中,如果我提供一个非常大的字符串,比如说几百个字母数字
*****在控制台输出是:
61
0
***** 字符串缓冲区始终以 0 毫秒计算,我的字符交换算法根据字符串大小进行计算
问。为什么我的交换算法不能在 0 毫秒内完成,为什么 stringbuffer 总是在 0 毫秒内完成?
我检查了 Java 源代码, StringBuffer.reverse() 实现如下:
public AbstractStringBuilder reverse() {
boolean hasSurrogate = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; --j) {
char temp = value[j];
char temp2 = value[n - j];
if (!hasSurrogate) {
hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
|| (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
}
value[j] = temp2;
value[n - j] = temp;
}
if (hasSurrogate) {
// Reverse back all valid surrogate pairs
for (int i = 0; i < count - 1; i++) {
char c2 = value[i];
if (Character.isLowSurrogate(c2)) {
char c1 = value[i + 1];
if (Character.isHighSurrogate(c1)) {
value[i++] = c1;
value[i] = c2;
}
}
}
}
return this;
}
问。请解释代理人的事情。
Q1:存在性能差异,因为您的交换代码创建了很多要操作的 String
对象,而另一个例程直接使用 char 数组并且不需要创建额外的对象。让我们检查一下您的代码行:
s=s.substring(0, i)+right+s.substring(i+1, s.length()-(i+1))+left+s.substring(s.length()-i, s.length());
它做这样的工作:
s = [new String 1] + char + [new String 2] + char + [new String 3]
这是 4 个新的 String
对象(显示的三个对象,加上添加 String
个对象后产生的对象。此外,显示的 3 个新字符串中的每一个都调用了 substring处理时间。此外,您在 for 循环中完成所有这些工作,因此它会针对每个字符重复!
字符串操作方便但昂贵。数组操作是直接的,不需要额外的对象或内存块,因此速度要快得多。
Q2:代理是 unicode 字符的一种特殊情况,创建它是为了处理更长的 unicode 字符。有关详细信息,请参阅 this article。代理项的 hi/low 部分的顺序很重要,因此交换代码将这两个字符颠倒是错误的,因此如果找到它们,它们的顺序将按原样放回去。