我想知道哪个程序变体更好运行时间?
两种变体看起来都很容易实现。但什么是更好的使用和在哪些情况下?
字符串反转:
public static String reverse(String s)
{
String rev = "";
for (int i = s.length() - 1; i >= 0; i--)
rev += s.charAt(i);
return rev;
}
StringBuilder反向:
public static String reverse(String s)
{
StringBuilder rev = new StringBuilder();
for (int i = s.length() - 1; i >= 0; i--)
rev.append(s.charAt(i));
return rev.toString();
}
答案 0 :(得分:6)
在你的两个案例中:我更喜欢第二个
因为compiler will convert the first one from:
rev += s.charAt(i);
到:
(new StringBuilder()).append(rev).append(s.charAt(i)).toString();
但是,see the worst case scenario:
public class Main
{
public static void main(String[] args)
{
long now = System.currentTimeMillis();
slow();
System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");
now = System.currentTimeMillis();
fast();
System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
}
private static void fast()
{
StringBuilder s = new StringBuilder();
for(int i=0;i<100000;i++)
s.append("*");
}
private static void slow()
{
String s = "";
for(int i=0;i<100000;i++)
s+="*";
}
}
输出将是:
slow elapsed 173 ms
fast elapsed 1 ms
答案 1 :(得分:5)
考虑到你可以这样做,两者都不是很好:
new StringBuilder(str).reverse().toString();
如果你必须使用上面的一个,那么选择StringBuilder反向 - 用第一个你可以通过屋顶发送GC创建和处理尽可能多的字符串对象有角色。
答案 2 :(得分:0)
String
类是不可变的,并且在他的生活中不能改变,并且两个字符串的连接创建新的String
并返回,但是StringBuilder
是一个可变的字符序列,可以更改内存中字符串的字符,使用StringBuilder
应该更好
作为另一种解决方案,您可以将字符串转换为char数组和反向数组,最后转换为String
char[] arr = s.toCharArray();
char tmp;
int maxIndex = arr.length-1;
for( int i = arr.length>>2; i>=0;i--) {
tmp = arr[i];
arr[i] = arr[maxIndex-i];
arr[maxIndex-i] = tmp;
}
return new String(arr);
有关详细信息,请参阅javadoc:StringBuilder,String
并查看StringBuilder
类源代码以了解想要在添加字符时实际发生
答案 3 :(得分:0)
一些有趣的细节。
我们可以编写一个递归函数来反转字符串而不使用任何循环。使用String方法substring()
:
public static String reverse(String s) {
int N = s.length();
if (N <= 1) return s;
String a = s.substring(0, N/2);
String b = s.substring(N/2, N);
return reverse(b) + reverse(a);
}
这种方法的效率如何? 此方法具有线性运行时间。