Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b7Sr2zcoRD2watXv1G
string-format
Companion code for the ankurm.com post "String.format, formatted() and printf in Java: The Complete Cheat Sheet."
Module in java-core-examples, the Java-core series.
Versions this was built and tested against
| Component | Version | Notes |
|---|---|---|
| JDK | 25.0.5+8 (Temurin, LTS) | String.format is Java 5; String.formatted() arrived in Java 15; Formatter parsing was rewritten without regex in Java 17. |
| JUnit Jupiter | 5.11.0 | |
| Maven | 3.9.11 |
Quickstart
export JAVA_HOME=/path/to/jdk-25
mvn compile
scripts/run.sh IndianGroupingDemo # one demo
scripts/run-all.sh # regenerate every file in output/
What's in here
| File | What it shows |
|---|---|
BasicsDemo.java |
Every part of %[index$][flags][width][.precision]conversion, changed one at a time. |
ReportTableDemo.java |
Left/right alignment, zero padding, truncation with %.Ns, a fixed-width invoice, printf. |
RoundingDemo.java |
%f rounds HALF_UP on the decimal string, so it disagrees with C printf and with BigDecimal(double). |
IndianNumberFormat.java + IndianGroupingDemo.java |
The main exhibit. Every built-in route to lakh/crore grouping tried and shown to fail, then a 60-line formatter that works. |
LocaleDemo.java |
The same %,.2f under six locales; the default-locale trap; what is not localized. |
FormatErrorsDemo.java |
Twelve format strings that compile and then throw (or, for "50% off", throw something surprising), with the real exception text. |
FormattedAndPrintfDemo.java |
format / formatted / printf / Formatter are one engine; text-block pairing; varargs and arrays. |
DateTimeDemo.java |
%tF, %tT, %tA on java.time values, localized names, and why %tH on a LocalDate throws. |
ConcatBenchmarkDemo.java |
Indicative cost of +, StringBuilder, formatted, format. A warmed plain loop, not JMH. |
StringFormatTest.java |
Pins every claim above as an assertion, 11/11 passing. |
scripts/printf_compare.c |
The same values through C printf, for the rounding comparison. |
output/01-11 |
Captured runs of everything above. Timing in 08 drifts between runs. |
Notes worth knowing before reading the post
%,dcannot produce lakh/crore grouping in any locale.en_INandhi_INboth print123,456,789(output/04). The,flag takes one grouping size fromDecimalFormat.getGroupingSize(), and aDecimalFormatbuilt from#,##,##0reports a grouping size of 3."Discount 50% off"throwsMissingFormatArgumentException, not an unknown-conversion error:% oparses as the space flag plus the octal conversion (output/06).%fon adoublerounds the decimal string,%fon aBigDecimalrounds the exact value, so2.675formats as2.68one way and2.67the other (output/03).
License
MIT - see the repo-wide LICENSE.