patternjavaMinor
Poke-a-Dot (Provider)
Viewed 0 times
pokeproviderdot
Problem
I need to create variable-length strings of dots/periods/full-stops to add to some text content, in a way that is similar to a formatted table-of-contents:
I know that things like
The code is complicated by the need for there to be many threads doing similar work at the same time.
I have written this utility class that caches a 'base' string in a Thread-local, and uses that to supply the required data.
Are there any alternatives, improvements, or other recommendations you have?
As an example usage, this is one of the ways that the above code is used. There are other places too:
Chapter 1 .................................... 1
Section 1.1 ................................ 1
Subsection 1.1.2 .......................... 12I know that things like
String.format exist, but that is not suitable for formatting periods this way.The code is complicated by the need for there to be many threads doing similar work at the same time.
I have written this utility class that caches a 'base' string in a Thread-local, and uses that to supply the required data.
Are there any alternatives, improvements, or other recommendations you have?
public final class DotPadding {
private static final ThreadLocal PAD_BASE = new ThreadLocal() {
@Override
protected String initialValue() {
return "................";
}
};
public static final String getPadding(final int length) {
if (length = length) {
return base.substring(0, length);
}
while (base.length() < length) {
base = base.concat(base);
}
PAD_BASE.set(base);
return base.substring(0, length);
}
}As an example usage, this is one of the ways that the above code is used. There are other places too:
String description = getFormattedDescription(title);
String index = getFormattedIndex(page);
String line = description
+ " "
+ DotPadding.getPadding(width - (2 + description.length() + index.length()))
+ " "
+ index;
System.out.println(line);Solution
-
Naive approach: use
Anyway, I suppose you did some profiling and it turned out that this is a bottleneck. Otherwise I'd really not complicate it with the
-
There is one exception (according to the source which Eclipse brings up for Java 8) when
So, in an average case the naive approach would create less new
-
Another idea is storing an array of strings in the
-
Naive approach: use
StringUtils.repeat (source) without the ThreadLocal:public static String repeat(final char ch, final int repeat) {
final char[] buf = new char[repeat];
for (int i = repeat - 1; i >= 0; i--) {
buf[i] = ch;
}
return new String(buf);
}Anyway, I suppose you did some profiling and it turned out that this is a bottleneck. Otherwise I'd really not complicate it with the
ThreadLocal nor the doubling/concatenation logic.-
substring in Java 6 used the same character array as the original String instance but it was changed in Java 7. So, substring calls copies the character array anyway, therefore string doubling and calling substring does not seem beneficial to me. (Anyway, it should be measured.)There is one exception (according to the source which Eclipse brings up for Java 8) when
beginIndex is zero and endIndex is the length of the original string. In this case substring returns the same String instance without copying. This case seems unlikely here, I guess there's a little chance that PAD_BASE.lenght will be the same as the length parameter since the while loop doubles the size of the padding string on every iteration.So, in an average case the naive approach would create less new
String (and underlying char[]) objects here than the one with substring.-
Another idea is storing an array of strings in the
ThreadLocal and extending the array on demand if the required lenght is longer than paddings.lenght:String paddings[] = new String[max];
for (int i = 0; i < max; i++) {
paddings[i] = StringUtils.repeat('.', i);
}-
2 could be a named constant.Code Snippets
public static String repeat(final char ch, final int repeat) {
final char[] buf = new char[repeat];
for (int i = repeat - 1; i >= 0; i--) {
buf[i] = ch;
}
return new String(buf);
}String paddings[] = new String[max];
for (int i = 0; i < max; i++) {
paddings[i] = StringUtils.repeat('.', i);
}Context
StackExchange Code Review Q#45885, answer score: 4
Revisions (0)
No revisions yet.