Java 字符串参数化 - 间接 toString 方法的性能损失
Java String Parameterization - Performace loss on indirect toString methods
我有一个 method
这样的:
private String getOrderListAsString() {
StringBuilder str = new StringBuilder();
str.append("Sell list:");
for (Order o : sellOrderList) {
str.append("\nSale: ").append(o);
}
str.append("Buy list:");
for (Order o : buyOrderList) {
str.append("\nBuy: ").append(o);
}
return str.toString();
}
它是通过日志参数化调用的,如下所示:
我们正在使用 java.util.logging 作为记录器。
logger.log(Level.INFO, "{0}", getOrderListAsString());
问题是,即使记录器级别为 Level.OFF
,字符串连接仍在进行。
为了解决这个问题,我们在方法的开头添加了一个 if
语句:
// Declaration:
boolean shouldLog = DebugWriter.getInstance().getLogger().getLevel() != Level.OFF;
// Usage in function:
if(!shouldLog) return null;
但感觉这可以用更聪明的方式来完成。提前致谢!
java.util.logging 具有采用 Supplier<String>
但未与格式字符串组合的重载。所以你可以这样使用它:
logger.info(() -> getOrderListAsString());
或者创建一个具有 toString()
方法的新抽象 OrderList
。然后你可以简单地将它作为参数传递,如果需要,记录器将调用 toString()
。
与 Eran 的回答精神相同,但只是包装参数而不是更改日志实现
public class LazyToString
{
private final Supplier<String> stringSupplier;
public LazyToString(Supplier<String> stringSupplier)
{
this.stringSupplier = stringSupplier;
}
@Override
public String toString()
{
return stringSupplier.get();
}
}
示例用法:
log.info("Something happened {}", new LazyToString(this::getOrderListAsString));
如果这太冗长,您可以创建一个静态方法调用来创建对象而不是使用 new,也许看起来像这样
log.info("Something happened {}", lazy(this::getOrderListAsString));
如果您使用的是 Java 8+,则 java.util.Logger 具有 log
方法的重载,该方法采用 Supplier
public void log(Level level,
Supplier<String> msgSupplier)
现在,您可以使供应商生成的字符串类似于
logger.log(Level.INFO, () -> getOrderListAsString());
或者,使用方法参考
logger.log(Level.INFO, this::getOrderListAsString);
我有一个 method
这样的:
private String getOrderListAsString() {
StringBuilder str = new StringBuilder();
str.append("Sell list:");
for (Order o : sellOrderList) {
str.append("\nSale: ").append(o);
}
str.append("Buy list:");
for (Order o : buyOrderList) {
str.append("\nBuy: ").append(o);
}
return str.toString();
}
它是通过日志参数化调用的,如下所示: 我们正在使用 java.util.logging 作为记录器。
logger.log(Level.INFO, "{0}", getOrderListAsString());
问题是,即使记录器级别为 Level.OFF
,字符串连接仍在进行。
为了解决这个问题,我们在方法的开头添加了一个 if
语句:
// Declaration:
boolean shouldLog = DebugWriter.getInstance().getLogger().getLevel() != Level.OFF;
// Usage in function:
if(!shouldLog) return null;
但感觉这可以用更聪明的方式来完成。提前致谢!
java.util.logging 具有采用 Supplier<String>
但未与格式字符串组合的重载。所以你可以这样使用它:
logger.info(() -> getOrderListAsString());
或者创建一个具有 toString()
方法的新抽象 OrderList
。然后你可以简单地将它作为参数传递,如果需要,记录器将调用 toString()
。
与 Eran 的回答精神相同,但只是包装参数而不是更改日志实现
public class LazyToString
{
private final Supplier<String> stringSupplier;
public LazyToString(Supplier<String> stringSupplier)
{
this.stringSupplier = stringSupplier;
}
@Override
public String toString()
{
return stringSupplier.get();
}
}
示例用法:
log.info("Something happened {}", new LazyToString(this::getOrderListAsString));
如果这太冗长,您可以创建一个静态方法调用来创建对象而不是使用 new,也许看起来像这样
log.info("Something happened {}", lazy(this::getOrderListAsString));
如果您使用的是 Java 8+,则 java.util.Logger 具有 log
方法的重载,该方法采用 Supplier
public void log(Level level,
Supplier<String> msgSupplier)
现在,您可以使供应商生成的字符串类似于
logger.log(Level.INFO, () -> getOrderListAsString());
或者,使用方法参考
logger.log(Level.INFO, this::getOrderListAsString);