44.5 Performance and Best Practices
Optimize formatting for high-throughput scenarios and ensure thread safety.
44.5.1 Reuse Formatter Instances
// BAD: creates new formatter each call
String format(double d) {
return new DecimalFormat("#,##0.00").format(d);
}
// GOOD: reuse in single-threaded context
private final DecimalFormat df = new DecimalFormat("#,##0.00");
String format(double d) { return df.format(d); }
44.5.2 ThreadLocal for Concurrent Use
private static final ThreadLocal<DecimalFormat> formatter =
ThreadLocal.withInitial(() -> new DecimalFormat("#,##0.00"));
public String format(double d) {
return formatter.get().format(d);
}
44.5.3 String.format for Simple Cases
// Quick and readable for non-localized formatting
String s1 = String.format("%.2f", 1234.567); // "1234.57"
String s2 = String.format("%,.2f", 1234.567); // "1,234.57" (grouping)
Use DecimalFormat when locale awareness or complex patterns are needed.
44.5.4 JMH Benchmark Sketch
// Requires org.openjdk.jmh:jmh-core and jmh-generator-annprocess
import org.openjdk.jmh.annotations.*;
import java.text.DecimalFormat;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
public class FormatBench {
DecimalFormat df = new DecimalFormat("#,##0.00");
double val = 1234.567;
@Benchmark public String decimalFormat() { return df.format(val); }
@Benchmark public String stringFormat() { return String.format("%,.2f", val); }
}
44.5.5 Validation and Testing
// Round-trip test
DecimalFormat df = new DecimalFormat("#,##0.00");
df.setParseBigDecimal(true);
BigDecimal original = new BigDecimal("1234.56");
String formatted = df.format(original);
try {
BigDecimal parsed = (BigDecimal) df.parse(formatted);
assert original.compareTo(parsed) == 0;
} catch (java.text.ParseException e) { /* fail */ }
44.5.6 Best Practices Checklist
- Cache formatters; avoid repeated instantiation
- Use
ThreadLocalfor concurrent scenarios - Set explicit rounding modes for financial data
- Test locale-specific formats on target locales
- Prefer
BigDecimalformatting for monetary values