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 ThreadLocal for concurrent scenarios
  • Set explicit rounding modes for financial data
  • Test locale-specific formats on target locales
  • Prefer BigDecimal formatting for monetary values