您的位置:首页 > 其它

字符串反转及性能测试

2015-11-25 21:31 281 查看
方法一:

创建一个临时字符串temp, 通过charAt方法倒序获取字符串的字符。

String temp = "";
String str = "我是中国人";
int length = str.length();
for (int j = length - 1; j >= 0; j--) {
temp += str.charAt(j);
}
System.out.println(temp);


方法二:

参考StringBuffer和StringBuilder继承的抽象类AbstractStringBuilder的reverse方法实现。该方法采用的是折半算法,从中间开始置换

public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
//折半算法,遍历并且首尾相应位置置换
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
//判断字符是否属于Surrogate区
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}


一个完整的Unicode字符叫代码点CodePoint,而一个Java char叫代码单元code unit。如果String 对象以UTF-16保存 Unicode 字符,需要用2个字符表示一个超大字符集的汉字,这这种表示方式称之为 Surrogate,第一个字符叫Surrogate High,第二个就是Surrogate Low。

代码点(Code Point)就是指Unicode中为字符分配的编号,一个字符只占一个代码点,例如我们说到字符“汉”,它的代码点是U+6C49.代码单元(Code Unit)则是针对编码方法而言,它指的是编码方法中对一个字符编码以后所占的最小存储单元。 例如UTF-8中,代码单元是一个字节,因为一个字符可以被编码为1个,2个或者3个4个字节;在UTF-16中,代码单元变成了两个字节(就是一个 char),因为一个字符可以被编码为1个或2个char(你找不到比一个char还小的UTF-16编码的字符,嘿嘿)。说得再罗嗦一点,一个字符,仅仅对应一个代码点,但却可能有多个代码单元(即可能被编码为2个char)。

更多的参考:Java中的字符集编码入门

private void reverseAllValidSurrogatePairs() {
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;
}
}
}
}


简单的测试一下这两种方法:

方法一循环100w次:

测试代码:

long startTime1 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String temp = "";
String str = "我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人";
int length = str.length();
for (int j = length - 1; j >= 0; j--) {
temp += str.charAt(j);
}
System.out.println(temp);
}
long endTime1 = System.currentTimeMillis();
System.out.println((endTime1 - startTime1) / 1000.0);
结果:



方法二循环100w次:

测试代码:

long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
StringBuffer sb = new StringBuffer("我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人我是中国人");
System.out.println(sb.reverse());
}
long endTime = System.currentTimeMillis();
System.out.println((endTime - startTime) / 1000.0);
结果:



可以看出,采用AbstractStringBuilder.reverse方法,内存使用率大大降低,打算买本算法的书学习学习,感觉好叼。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  折半 反转 reverse