gpt4 book ai didi

java - 遍历String中包含的字符时,是否最好在for循环语句的内部或外部调用length方法?

转载 作者:行者123 更新时间:2023-12-01 19:07:24 26 4
gpt4 key购买 nike

在Java中,当您必须在条件部分中调用String的for方法时,使用length循环遍历String的最佳方法是什么。

即for循环流程图:

for loop flowchart

for(initialization ; condition ; increment) {
...
}


由于条件是在每次递增之后执行的,所以不是每次都会调用 length方法吗?

loopOutside

final int length = str.length();
for(int i = 0; i < length; i++) {
...
}




loopInside

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


Java Microbenchmark线束(JMH)

JMH版本:1.22
VM版本:JDK 13.0.1,OpenJDK 64位服务器VM,13.0.1 + 9

以下数字仅是数据。为了获得可重用的见解,您需要跟进为什么数字如此。不要假设数字告诉您您希望他们告诉什么。

Benchmark                (stringLength)  Mode  Cnt      Score     Error  Units
MyBenchmark.loopOutside 0 avgt 5 0.851 ± 0.012 ns/op
MyBenchmark.loopOutside 1 avgt 5 5.999 ± 0.003 ns/op
MyBenchmark.loopOutside 16 avgt 5 90.316 ± 2.981 ns/op
MyBenchmark.loopOutside 64 avgt 5 356.891 ± 0.472 ns/op
MyBenchmark.loopOutside 256 avgt 5 1417.282 ± 7.433 ns/op
MyBenchmark.loopOutside 512 avgt 5 2867.486 ± 12.225 ns/op
MyBenchmark.loopOutside 2048 avgt 5 11444.621 ± 384.349 ns/op
MyBenchmark.loopInside 0 avgt 5 0.859 ± 0.011 ns/op
MyBenchmark.loopInside 1 avgt 5 5.158 ± 0.039 ns/op
MyBenchmark.loopInside 16 avgt 5 78.949 ± 0.089 ns/op
MyBenchmark.loopInside 64 avgt 5 312.579 ± 0.603 ns/op
MyBenchmark.loopInside 256 avgt 5 1245.757 ± 0.724 ns/op
MyBenchmark.loopInside 512 avgt 5 2498.118 ± 18.413 ns/op
MyBenchmark.loopInside 2048 avgt 5 9947.116 ± 254.583 ns/op


package org.sample;

import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(1)
@State(Scope.Benchmark)
public class MyBenchmark
{
@Param({"0", "1", "16", "64", "256", "512", "2048"})
private int stringLength;

private String str;

@Setup
public void setup()
{
str = new Random().ints(97, 123)
.limit(stringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}

@Benchmark
public void loopOutside(Blackhole bh)
{
final int length = str.length();
for(int i = 0; i < length; i++)
bh.consume(str.charAt(i));
}

@Benchmark
public void loopInside(Blackhole bh)
{
for(int i = 0; i < str.length(); i++)
bh.consume(str.charAt(i));
}

public static void main(String[] args) throws RunnerException
{
Options opt = new OptionsBuilder().include(MyBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}


我假设运行时即时(JIT)编译器可以通过删除多余的 length方法调用来进行优化。因为值不变。这样,我们可以在不牺牲性能的情况下提高可读性。

参考文献:
Fastest way to iterate over all the chars in a String
What is the easiest/best/most correct way to iterate through the characters of a string in Java?

最佳答案

这个琐碎的问题是在查看其他人的源代码时出现的。我对自己想:如果在length循环的条件部分中调用for方法有关系吗?事实证明,并非如此。 (我在询问时已经回答了这个问题。)

因此,最好将length方法调用保留在循环语句中:

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

或(如果您担心,但很可能不会成为瓶颈。)

for(int i = 0, n = str.length(); i < n; i++)

我最喜欢这个毫无意义的问题是,它使我熟悉了事实上的Java微优化工具:JMH。 (如评论中所述,我应该使用更大的字符串长度)

关于java - 遍历String中包含的字符时,是否最好在for循环语句的内部或外部调用length方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59525353/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com