JAVA实现字符串反转(Reverse)的⽅法(没有最快,只有更
快)
字符串反转在Java程序笔试⾯试中经常遇到,程序出了满⾜设计需要外,往往我们还要考虑到性能及内存相关的问题,如果考虑到性能和内存相关的问题,在笔试或⾯试中更容易赢得考官的青睐。
不多说,给出我这边实现的⼏种⽅案:
⽅案⼀:
private static String reverse(String str) {
if (str == null) {
return null;
}
return new StringBuffer(str).reverse().toString();
}
利⽤StringBuffer或StringBuilder⾃带reverse⽅法,简单!
⽅案⼆:
private static String reverse1(String str) {
if (str == null) {
return null;
}
String result = "";
for (int i = str.length() - 1; i >= 0; i--) {
result = result + str.charAt(i);
}
return result;
}
利⽤String的charAt⽅法,逆序拼接。
⽅案三:
private static String reverse2(String str) {
if (str == null) {
return null;
}
String result = "";
char[] chars = CharArray();
for (int i = chars.length - 1; i >= 0; i--) {
result = result + chars[i];
}
return result;
}
利⽤String的toCharArray⽅法,逆序拼接。
⽅案四:
private static String reverse3(String str) {
if (str == null) {
return null;
}
int stackSize = str.length();
Stack theStack = new Stack();
for (int i = 0; i < stackSize; i++) {
theStack.push(str.charAt(i));
}
String result = "";
while (!theStack.isEmpty()) {
char ch = (char) theStack.pop();
result = result + ch;
}
return result;
}
利⽤栈,压栈出栈来逆序。
⽅案五:
private static String reverse4(String str) {
if (str == null) {
return null;
}
char[] chars = CharArray();
int n = chars.length - 1;
for (int i = 0; i < chars.length / 2; i++) {
char temp = chars[i];
chars[i] = chars[n - i];
chars[n - i] = temp;
}
return new String(chars);
}
⼆分法逆序字符串数组。
以上⽅法是容易想到的,都可以实现字符串逆序的功能。我们可以测试下上述五种⽅法执⾏的效率。
import java.util.Random;
import java.util.Stack;
public class TestStringReverse {
public static void main(String[] args) {
// 实例⼀个长度为100000的字符串
String test = "";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 100000; i++) {
sb.Int(10));
}
test = sb.toString();
// ⽅法1
long start1 = System.nanoTime();
String reverse1 = reverse1(test);
System.out.println("reverse1 time = " + (System.nanoTime() - start1));
// ⽅法2
long start2 = System.nanoTime();
String reverse2 = reverse2(test);
System.out.println("reverse2 time = " + (System.nanoTime() - start2));
// ⽅法3
// ⽅法3
long start3 = System.nanoTime();
String reverse3 = reverse3(test);
System.out.println("reverse3 time = " + (System.nanoTime() - start3));        // ⽅法4
long start4 = System.nanoTime();
String reverse4 = reverse4(test);
System.out.println("reverse4 time = " + (System.nanoTime() - start4));        // ⽅法5
long start5 = System.nanoTime();
String reverse5 = reverse5(test);
System.out.println("reverse5 time = " + (System.nanoTime() - start5));        System.out.println(test);
System.out.println(reverse1);
System.out.println(reverse2);
System.out.println(reverse3);
System.out.println(reverse4);
System.out.println(reverse5);
}
private static String reverse1(String str) {
if (str == null) {
return null;
}
return new StringBuffer(str).reverse().toString();
}
private static String reverse2(String str) {
if (str == null) {
return null;
}
String result = "";
for (int i = str.length() - 1; i >= 0; i--) {
result = result + str.charAt(i);
}
return result;
}
private static String reverse3(String str) {
if (str == null) {
return null;
}
String result = "";
char[] chars = CharArray();
for (int i = chars.length - 1; i >= 0; i--) {
result = result + chars[i];
}
return result;
}
private static String reverse4(String str) {
if (str == null) {
return null;
}
int stackSize = str.length();
Stack theStack = new Stack();
for (int i = 0; i < stackSize; i++) {
theStack.push(str.charAt(i));
}
String result = "";
while (!theStack.isEmpty()) {
char ch = (char) theStack.pop();
result = result + ch;
nextint()方法}
}
return result;
}
private static String reverse5(String str) {
if (str == null) {
return null;
}
char[] chars = CharArray();
int n = chars.length - 1;
for (int i = 0; i <= chars.length / 2; i++) {
char temp = chars[i];
chars[i] = chars[n - i];
chars[n - i] = temp;
}
return new String(chars);
}
}
运⾏结果:(⽅法⼀到五对应时间分别为reverse1到reverse5,⽅法执⾏时间使⽤纳秒计时单位)
reverse1 time = 3206954
reverse2 time = 5384374368
reverse3 time = 1996738321
reverse4 time = 1471417533
reverse5 time = 1476173
因为测试时间具有随机性,所以测试多组,五种⽅法耗时关系:reverse2>reverse3>reverse4>reverse1>reverse5.
简单分析下:
Java官⽅API解释:
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. For additional information on string concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification.
意思是:Java语⾔为字符串连接运算符(+)提供特殊⽀持,并为其他对象转换为字符串。 字符串连接是通
过StringBuilder (或StringBuffer )类及其append⽅法实现的。 另外字串在拼接⽣成新字串的时候,实际上是在不断的创建新的对象,⽽原来的对象就会变为垃圾被GC回收掉,可想⽽知这样执⾏效率会有多低。
所以:reverse2注定⽐reverse1慢
⽅法三和⽅法四实现上其实也有字串的循环拼接,所以⾃然也⽐reverse1慢。
从⽅法三和⽅法四时间快慢看,charAt的效率⽐char数组取指定index的字符效率低,时间也是如此。
所以:reverse2>reverse3>reverse4>reverse1
⽅法五⽐⽅法1要快,这个可以从StringBuffer源码上分析:
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;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}
/** Outlined helper method for reverse() */
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;
}
}
}
}
可以看出,StringBuffer逆序也是基于char数组,循环次数(时间复杂度)⽐⽅法五要多。
从⽽reverse1>reverse5
所以:reverse2>reverse3>reverse4>reverse1>reverse5.
最后,关于字符串逆序⽅法应该还有其他⽅法,后续如发现⽐⽅法五还⾼效的⽅法会补充。
备注:
1.⼤家如有更⾼效⽅法,请留⾔补充;
2.⽅法暂时未考虑空间复杂度,⼀般来说⾼效的⽅法或多或少空间复杂度⾼,即所谓的空间换时间。