【问题标题】:Is it a good practice to put String.toCharArray() into for loop [duplicate]将 String.toCharArray() 放入 for 循环是一种好习惯吗?
【发布时间】:2016-08-10 20:45:19
【问题描述】:

我多次遇到如下代码:

for (char c : s.toCharArray()) {
    ....
}

我想知道s.toCharArray() 是只执行一次还是执行s.length 次?那么下面的案例呢?

for (int i = 0; i < s.toCharArray().length; i++) {
    ....
}

受cmets启发,做了一些测试:

案例1:执行时间:692.664

    String s = "dfsdfjglsdlghsl";
    for(int i = 0 ; i < 25; i++){
        s += s;
    }
    long start_time = System.nanoTime();

    for(char c : s.toCharArray()){
        int i = 0;
    }

    long end_time = System.nanoTime();
    double excution_time = (end_time - start_time)/1e6;
    System.out.println(excution_time);

案例2:执行时间:688.217

    String s = "dfsdfjglsdlghsl";
    for(int i = 0 ; i < 25; i++){
        s += s;
    }
    long start_time = System.nanoTime();

    char[] carrays = s.toCharArray();
    for(char c : carrays){
        int i = 0;
    }

    long end_time = System.nanoTime();
    double excution_time = (end_time - start_time)/1e6;
    System.out.println(excution_time);

几乎一样。所以,s.toCharArray() 在第一种情况下应该只执行一次。

【问题讨论】:

  • 只执行一次。您可以找到与增强的 for 循环 in JLS 等效的基本 for 循环(搜索“否则,表达式必须具有数组类型,T[]。”)。
  • 在第二个示例中,每次执行循环时都会调用 s.toCharArray().length。这很不幸,因为它每次都将字符串复制到一个新数组中,这使得这个 for 循环在字符串长度上至少是二次的。它在功能上也等价于常数时间表达式s.length();我推荐后者。
  • +1 表示 Any 的评论,我想这可以变成答案。我的评论是:在调试器中执行这个并设置一个断点来观察 Andy 的声明。

标签: java string char


【解决方案1】:

根据JLS Sec 14.14.2,对数组类型的增强 for 语句:

L1: L2: ... Lm:
for ({VariableModifier} TargetType Identifier : Expression) {
  Statement
}

相当于下面的基本for语句:

T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
    {VariableModifier} TargetType Identifier = #a[#i];
    Statement
}

所以:

for (char c : s.toCharArray()) {
  // ...
}

相当于:

T[] cs = s.toCharArray();
for (int i = 0; i < cs.length; i++) {
    char c = cs[i];
    // ...
}

所以s.toCharArray() 只执行一次。

然而,在

for (int i = 0; i < s.toCharArray().length; i++) {

s.toCharArray() 在每次循环迭代之前执行。这是不可取的,因为它会创建一个长度为s.length() 的新数组,将字符复制到该数组中,然后获取数组的长度并丢弃数据。

由于循环执行了s.length() 次,因此该循环至少是字符串长度的二次方。

使用起来计算成本要低得多:

for (int i = 0; i < s.length(); i++) {

在字符串长度上是线性的。

【讨论】:

    猜你喜欢
    • 2014-11-05
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 2022-01-20
    • 2012-05-30
    • 2021-02-13
    • 2023-03-06
    • 2016-12-03
    相关资源
    最近更新 更多