我有一个记录和跟踪相关代码,在整个代码中经常调用,特别是在打开跟踪时。 StringBuilder用于构建String。字符串具有合理的最大长度,我想大约数百个字符。
问题:现有的库是否可以执行以下操作:
// in reality, StringBuilder is final,
// would have to create delegated version instead,
// which is quite a big class because of all the append() overloads
public class SmarterBuilder extends StringBuilder {
private final AtomicInteger capRef;
SmarterBuilder(AtomicInteger capRef) {
int len = capRef.get();
// optionally save memory with expense of worst-case resizes:
// len = len * 3 / 4;
super(len);
this.capRef = capRef;
}
public syncCap() {
// call when string is fully built
int cap;
do {
cap = capRef.get();
if (cap >= length()) break;
} while (!capRef.compareAndSet(cap, length());
}
}
为了利用这一点,我的与日志相关的类将具有一个具有适当范围的共享capRef
变量。
(奖金问题:我很好奇,是否可以在没有循环的情况下进行syncCap()?)
动机:我知道StringBuilder的默认长度总是太少。我可以(并且目前确实)投入一个特殊的初始容量值100,这会导致在某些情况下调整大小,但并非总是如此。但是,我不喜欢源代码中的幻数,这个功能就是“优化一次,在每个项目中使用”。
答案 0 :(得分:1)
确保您进行了性能测量,以确保您真正为额外的工作获得了一些好处。
作为StringBuilder类的替代方法,请考虑StringBuilderFactory。它可以提供两个静态方法,一个用于获取StringBuilder,另一个用于在完成构建字符串时调用。您可以将StringBuilder作为参数传递给它,它会记录长度。 getStringBuilder方法将使用其他方法记录的统计信息来选择初始大小。
有两种方法可以避免在syncCap中循环:
在这种情况下忽略失败的论点是你只需要对实际长度进行随机抽样。如果另一个线程正在同时更新,那么无论如何您都会获得字符串长度的最新视图。
答案 1 :(得分:0)
您可以将每个字符串的字符串长度存储在统计数组中。运行你的应用程序,并在关机时取你的字符串长度的90%四分之一(排序所有str长度值,并取数组pos = sortedStrings.size()* 0,9
的长度值这样你创建了一个初始字符串构建器大小,其中90%的字符串都适合。
<强>更新强>
该值可以是硬编码的(如java对ArrayList中的值10执行),或从配置文件中读取,或在测试阶段自动计算。但是四分位计算不是免费的,所以最好你运行你的项目一段时间,在SmartBuilder内动态测量90%的四分之一,不时输出90%的四分之一,然后更改属性文件以使用该值点。
通过这种方式,您可以获得每个项目的最佳结果 或者,如果您更进一步:让智能生成器不时在配置文件中更新该值。 但这一切都不值得努力,你只会对数百万条目的数据,如数字路线图等做到这一点。