11

考虑这样的方法:

@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")和使用静态字段一样快?

4

5 回答 5

3

您无需担心代码运行时行分隔符会发生变化,因此我认为没有理由不缓存它。

缓存一个值肯定比一遍又一遍地执行调用要快,但差异可能可以忽略不计。

于 2013-08-04T17:09:37.357 回答
3

如果您已经意识到与此相关的性能问题,是的。

如果你没有,那么不,查找不太可能有足够的开销。

这将属于一般类别“微优化”和“过早优化”中的一个或两个。:-)


但是,如果您担心效率,您可能有更大的机会,因为您的toString方法每次都重新生成字符串。IftoString将被调用很多,而不是缓存行终止符,缓存生成的字符串,并在房间地图发生变化时清除它。例如:

@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;

划算(降压是额外字段的开销)。当然它是每个实例而不是每个类,所以(参考前面关于效率的评论)只有在你有充分理由的情况下才这样做。

于 2013-08-04T17:09:39.430 回答
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调用对所有字符串构建的整体影响非常非常不可能被注意到。

于 2013-08-04T17:31:44.720 回答
2

既然这么容易做到,何乐而不为呢?至少,实现System.getProperty()将必须进行哈希表查找(即使在内部缓存)以找到您请求的属性,然后getString()将在结果对象上调用虚拟方法。这些都不是很昂贵,但需要多次调用。更不用说String会创建许多临时对象并且之后需要 GCing。

如果将它移到循环顶部并重用相同的值,则可以避免所有这些问题。那为什么不呢?

于 2013-08-04T17:11:55.103 回答
0

如果系统属性保证在应用程序期间保持不变,则可以对其进行缓存,但通常您将失去该属性的特性,该特性在您更改它时会改变其行为。

例如,文本生成器可以使用该属性为 windows 或 linux 生成文本,并允许在应用程序中动态更改该属性,为什么不呢?

通常,捕获属性意味着使函数 setProperty 无用。

于 2017-12-08T00:25:45.310 回答