【问题标题】:Java - Most Efficent way to traverse a String [duplicate]Java - 遍历字符串的最有效方法[重复]
【发布时间】:2012-10-29 07:54:14
【问题描述】:

可能重复:
What is the easiest/best/most correct way to iterate through the characters of a string in Java?

我考虑的是时间和效率。考虑到这些,哪种方法(以下方法或其他未提及的方法)是遍历字符串每个字符的最有效方法?

String str = "Foo Bar";
for(int i=0;i<str.length();i++)
   System.out.println(str.charAt(i)); // access the character using .charAt()

for(char letter: str.toCharArray)
   System.out.println(letter);       // use for-each loop with the char array.

同样,可能有更好的方法来做到这一点,但我也很好奇上述两者之间是否存在重大的时间/资源差异。

【问题讨论】:

  • 严格来说,String 方法.charAt() 是 O(1) 并且可能比将字符串冗余转换为字符数组更快(因为字符串已经由 char 数组支持)

标签: java string


【解决方案1】:

第一种方法更快,因为toCharArray 必须在返回任何内容之前复制字符串的内部字符数组,而charAt 直接访问该内部数组中的元素,从而提高效率。

换句话说,charAtO(1)toCharArrayO(n)。现在,这两种遍历字符串的方法都是O(n),但第二种方法的“领先系数”比第一种方法高。

如果您查看 source codeString 类,您可以看到所有这些。

【讨论】:

    【解决方案2】:

    第一个版本效率更高。由于使用toCharArray() 创建和填充新的char[] 的成本,代码的第二个版本最终会变慢并使用更多内存。

    对于长字符串(大约超过 512 个字符),检查字符串的最快方法是使用反射访问 String 的支持 char[](但仅适用于 Java 8,因为 @ 987654321@):

    String data = "a really long string";
    Field field = String.class.getDeclaredField("value");
    field.setAccessible(true);
    char[] chars = (char[]) field.get(data);
    
    for (int i = 0, n = chars.length; i < n; i++)
        System.out.println(chars[i]);
    

    通过使用上述方法,我们能够完全避免创建新的char[] 的需要,并且还可以在每次迭代中支付对charAt() 的额外方法调用的成本。

    看看这个post,答案包含详细的基准。两全其美,但无论如何它是一个 hack,它不再有效。

    【讨论】:

    • 请注意缺少的field.setAccessible(true);
    • @Viliam 现在已修复,谢谢!
    • 这段代码在 OpenJDK 上运行时会被破坏,因为至少在 Java 9 中实现了Compact StringsString 中的 value 字段现在是一个字节数组。
    猜你喜欢
    • 2016-07-28
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2011-04-17
    • 2018-03-28
    • 2010-09-16
    • 2023-03-03
    相关资源
    最近更新 更多