Use StringBuilder.deleteCharAt(int)
and StringBuilder.delete(int, int)
to handle sanitization more effectively
Comment From: stsypanov
@rstoyanchev done.
I've also measured performance impact with simple benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g"})
public class DropDoubleSlashBenchmark {
@Benchmark
public String ineffective(Data data) {
String path = data.path;
while (true) {
int index = path.indexOf("//");
if (index == -1) {
break;
}
path = path.substring(0, index) + path.substring(index + 1);
}
return path;
}
@Benchmark
public String effective(Data data) {
StringBuilder path = new StringBuilder(data.path);
while (true) {
int index = path.indexOf("//");
if (index == -1) {
break;
}
path.deleteCharAt(index);
}
return path.toString();
}
@State(Scope.Thread)
public static class Data {
private final String path = "/home/" + "/path";
}
}
and got the following results on my machine
JDK 8
effective avgt 47.882 ± 1.801 ns/op
ineffective avgt 51.620 ± 0.907 ns/op
effective:·gc.alloc.rate.norm avgt 136.000 ± 0.001 B/op
ineffective:·gc.alloc.rate.norm avgt 224.000 ± 0.001 B/op
JDK 11
effective avgt 33.949 ± 0.188 ns/op
ineffective avgt 47.735 ± 0.519 ns/op
effective:·gc.alloc.rate.norm avgt 104.000 ± 0.001 B/op
ineffective:·gc.alloc.rate.norm avgt 152.000 ± 0.001 B/op
On longer strings I think we'll have even better improvement.