考虑这样的方法:
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
for (final Room room : map)
{
sb.append(room.toString());
sb.append(System.getProperty("line.separator")); // THIS IS IMPORTANT
}
return sb.toString();
}
System.getProperty("line.separator")
可以多次调用。
我应该使用public final static String lineSeperator = System.getProperty("line.separator")
缓存此值吗?
以后只使用lineSeperator
?
或System.getProperty("line.separator")
和使用静态字段一样快?
答案 0 :(得分:3)
在代码运行时,您不必担心行分隔符会发生变化,因此我认为没有理由不对其进行缓存。
缓存一个值肯定比反复执行一个调用更快,但差异可能可以忽略不计。
答案 1 :(得分:3)
我认为你的问题是错误的二分法。我不会每次都打getProperty
,也不会为它声明一个静态字段。我只是将其提取到toString
中的局部变量。
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
final String newline = System.getProperty("line.separator");
for (final Room room : map) sb.append(room.toString()).append(newline);
return sb.toString();
}
顺便说一下,我已经对电话进行了基准测试。代码:
public class GetProperty
{
static char[] ary = new char[1];
@GenerateMicroBenchmark public void everyTime() {
for (int i = 0; i < 100_000; i++) ary[0] = System.getProperty("line.separator").charAt(0);
}
@GenerateMicroBenchmark public void cache() {
final char c = System.getProperty("line.separator").charAt(0);
for (int i = 0; i < 100_000; i++) ary[0] = (char)(c | ary[0]);
}
}
结果:
Benchmark Mode Thr Cnt Sec Mean Mean error Units
GetProperty.cache thrpt 1 3 5 10.318 0.223 ops/msec
GetProperty.everyTime thrpt 1 3 5 0.055 0.000 ops/msec
缓存方法的速度提高了两个多个数量级。
请注意getProperty
调用所有字符串构建的整体影响非常非常不可能显着。
答案 2 :(得分:2)
既然这么容易,为什么不呢? 至少 System.getProperty()
的实现必须进行哈希表查找(即使在内部缓存)以查找您请求的属性,然后是虚方法getString()
将在生成的对象上调用。这些都不是非常昂贵,但需要多次调用。更不用说会创建许多String
个临时工具,之后需要GCing。
如果将其移到循环的顶部并重复使用相同的值,则可以避免所有这些问题。那为什么不呢?
答案 3 :(得分:1)
如果您发现了与此相关的性能问题,请确定。
如果你没有,那么不,查找不太可能有足够的开销。
这属于“微优化”和“过早优化”的一般或两个类别。 : - )
但是如果你担心效率,你可能会有一个多更大的机会,因为你的toString
方法每次都会重新生成字符串。如果toString
将被调用很多,而不是缓存行终止符,请缓存生成的字符串,并在房间地图发生变化时清除它。 E.g:
@Override
public String toString()
{
if (cachedString == null)
{
final StringBuilder sb = new StringBuilder();
final String ls = System.getProperty("line.separator");
for (final Room room : map)
{
sb.append(room.toString());
sb.append(ls);
}
cachedString = sb.toString();
}
return cachedString;
}
...当地图发生变化时,请执行
cachedString = null;
这是一个很多更多的降压(降压是额外场的开销)。虽然它是每个实例而不是每个类,所以(参考之前关于效率的评论)只有在你有充分理由的情况下才能这样做。
答案 4 :(得分:0)
如果系统属性在应用程序期间保证保持不变,则可以对其进行缓存,但通常会丢失属性的功能,这会在更改时改变行为。
例如,文本生成器可以使用该属性为Windows或Linux生成文本,并允许在应用程序中动态更改属性,为什么不呢?
通常,捕获属性意味着使函数setProperty变得无用。