哪个代码更有效?

时间:2011-10-25 02:38:08

标签: java tail-recursion optimization

以下哪一种方法可以有效地反转字符串中的单词?

public String Reverse(StringTokenizer st){
    String[] words = new String[st.countTokens()];
    int i = 0;
    while(st.hasMoreTokens()){
       words[i] = st.nextToken();i++}

    for(int j = words.length-1;j--)
       output = words[j]+" ";}

OR

public String Reverse(StringTokenizer st, String output){        
    if(!st.hasMoreTokens()) return output;        
        output = st.nextToken()+" "+output;
        return Reverse(st, output);}       

public String ReverseMain(StringTokenizer st){       
    return Reverse(st, "");}

虽然第一种方式似乎更具可读性和直接性,但它有两个循环。在第二种方法中,我尝试以尾递归方式进行。但我不确定java是否会优化尾递归代码。

4 个答案:

答案 0 :(得分:2)

  

但我不确定java是否会优化尾递归代码。

没有。或者至少Sun / Oracle Java实现不包括Java 7。

参考文献:


我不知道这是否使一个解决方案比另一个解决方案更快。 (自己测试一下......注意避免使用标准的微基准陷阱。)

但是,Java没有实现尾调用优化这一事实意味着如果你给第二个解决方案提供一个包含大量(足够)字数的字符串,那么第二个解决方案可能会耗尽堆栈空间。


最后,如果您正在寻找一种更节省空间的方式来实现这一点,那么只有StringBuilder才能使用。{/ p>

  1. 从您的输入StringBuilder
  2. 创建String
  3. 使用StringBuilder
  4. 反转reverse()中的字符
  5. 逐步执行StringBuilder,确定每个单词的开头和结尾偏移量。对于每个开始/结束偏移对,反转偏移之间的字符。 (您必须使用循环执行此操作。)
  6. StringBuilder转回String

答案 1 :(得分:2)

你可以在一个循环中完成这个

public String Reverse(StringTokenizer st){
    int length = st.countTokens();
    String[] words = new String[length];
    int i = length - 1;
    while(i >= 0){
      words[i] = st.nextToken();i--}
}

答案 2 :(得分:0)

您可以通过在大量结果上对两者进行计时来测试结果

例如。您可以反转100000000个字符串并查看它需要多少秒。您还可以比较开始和结束系统时间戳,以获得两个函数之间的确切差异。

答案 3 :(得分:0)

不推荐使用StringTokenizer,但如果您阅读了当前的JavaDoc ...

  

StringTokenizer是一个遗留类,出于兼容性原因而保留,尽管在新代码中不鼓励使用它。建议任何寻求此功能的人都使用String的split方法或java.util.regex包。

String[] strArray = str.split(" ");
StringBuilder sb = new StringBuilder();
for (int i = strArray.length() - 1; i >= 0; i--)
    sb.append(strArray[i]).append(" ");

String reversedWords = sb.substring(0, sb.length -1) // strip trailing space