Java 12 - CompactNumberFormat Examples
Need to format posts, followers, or likes in a social-media-style, where 37211 becomes 37.2k?
@NatGeoTravel Twitter
In Java 12, there is a new class, CompactNumberFormat. This is a subclass of NumberFormat that formats a decimal number in a compact form. NumberFormat is the abstract base class for all number formats which provides the interface for formatting and parsing numbers. NumberFormat also provides methods for determining which locales have number formats, and what their names are.
An example of a SHORT compact form would be writing 10,000 as 10K, only requiring three instead of five characters. NumberFormat and java.text.spi.NumberFormatProvider have been extended to include a new method, getCompactNumberInstance().
- static NumberFormat getCompactNumberInstance(): Returns a compact number format for the default FORMAT locale with "SHORT" format style.
- static NumberFormat getCompactNumberInstance(Locale locale,NumberFormat.Style formatStyle): Returns a compact number format for the specified locale and formatStyle.
There is also a related new enumeration, NumberFormat.Style, which has two values: LONG and SHORT.
import java.text.NumberFormat;
import java.util.Locale;
public class CompactNumberFormatExample {
public static void main(String args[]) {
NumberFormat nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println("NumberFormat.Style.SHORT:");
System.out.println("Result: " + nf.format(10000));
System.out.println("Result: " + nf.format(120300));
System.out.println("Result: " + nf.format(2120000));
System.out.println("Result: " + nf.format(1950000300));
nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.LONG);
System.out.println("\nNumberFormat.Style.LONG:");
System.out.println("Result: " + nf.format(10000));
System.out.println("Result: " + nf.format(120300));
System.out.println("Result: " + nf.format(2120000));
System.out.println("Result: " + nf.format(1950000300));
}
}
NumberFormat.Style.SHORT: Result: 10K Result: 120K Result: 2M Result: 2B NumberFormat.Style.LONG: Result: 10 thousand Result: 120 thousand Result: 2 million Result: 2 billion
NumberFormat's Locale
We can specify desired locale for our compact number format. It is easiest to understand via code example:
import java.text.NumberFormat;
import java.util.Locale;
public class CompactNumberFormatLocale {
private static void printCompactNumberFormatLocale(long number) {
NumberFormat nfDefault = NumberFormat.getCompactNumberInstance();
NumberFormat nfUsLong = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.LONG);
NumberFormat nfFrShort = NumberFormat.getCompactNumberInstance(Locale.FRANCE, NumberFormat.Style.SHORT);
NumberFormat nfFrLong = NumberFormat.getCompactNumberInstance(Locale.FRANCE, NumberFormat.Style.LONG);
NumberFormat nfChShort = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
NumberFormat nfChLong = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.LONG);
System.out.println("Compact Number Formatting for " + number + ":");
System.out.println("Default: " + nfDefault.format(number));
System.out.println("US Long: " + nfUsLong.format(number));
System.out.println("FR Short: " + nfFrShort.format(number));
System.out.println("FR Long: " + nfFrLong.format(number));
System.out.println("CH Short: " + nfChShort.format(number));
System.out.println("CH Long: " + nfChLong.format(number) + "\n");
}
public static void main(String[] arguments) {
printCompactNumberFormatLocale(345600);
printCompactNumberFormatLocale(23450000);
printCompactNumberFormatLocale(1230000000);
}
}
Compact Number Formatting for 345600: Default: 346K US Long: 346 thousand FR Short: 346 k FR Long: 346 mille CH Short: 35? CH Long: 35? Compact Number Formatting for 23450000: Default: 23M US Long: 23 million FR Short: 23 M FR Long: 23 million CH Short: 2345? CH Long: 2345? Compact Number Formatting for 1230000000: Default: 1B US Long: 1 billion FR Short: 1 Md FR Long: 1 milliard CH Short: 12? CH Long: 12?
Following code is a snippet to get all locales for which the get*Instance methods of NumberFormat can return.
// available locales
Locale[] locales = NumberFormat.getAvailableLocales();
for (Locale locale : locales) {
System.out.println(locale);
}
NumberFormat's FractionDigits
- void setMaximumFractionDigits(int newValue): Sets the maximum number of digits allowed in the fraction portion of a number. maximumFractionDigits must be ≥ minimumFractionDigits.
- void setMinimumFractionDigits(int newValue): Sets the minimum number of digits allowed in the fraction portion of a number. minimumFractionDigits must be ≤ maximumFractionDigits.
import java.text.NumberFormat;
import java.util.Locale;
public class CompactNumberFormatFractionDigits {
public static void main(String args[]) {
NumberFormat nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println("Minimum: " + nf.getMinimumFractionDigits());
System.out.println("Maximum: " + nf.getMaximumFractionDigits());
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setMaximumFractionDigits(1);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setMaximumFractionDigits(2);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
}
}
Minimum: 0 Maximum: 0 Result: 123K Result: 5M Result: 123.5K Result: 5.2M Result: 123.45K Result: 5.16M Result: 123.45K Result: 5.16M
The ability to use fraction digits leads to the ability to control compact number formatted output that is likely to be more aesthetically pleasing in needed cases.
NumberFormat's Rounding
By default RoundingMode.HALF_EVEN is used. We can set rounding mode by calling setRoundingMode(RoundingMode) method.
- void setRoundingMode(RoundingMode roundingMode): Sets the RoundingMode used in this NumberFormat.
The rounding related to fraction digits
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Locale;
public class CompactNumberFormatRounding {
public static void main(String args[]) {
NumberFormat nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setRoundingMode(RoundingMode.UP);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setMinimumFractionDigits(1);
nf.setMaximumFractionDigits(1);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
nf.setRoundingMode(RoundingMode.DOWN);
System.out.println("\nResult: " + nf.format(123454));
System.out.println("Result: " + nf.format(5156835));
}
}
Result: 123K Result: 5M Result: 123.45K Result: 5.16M Result: 123.46K Result: 5.16M Result: 123.5K Result: 5.2M Result: 123.4K Result: 5.1M
NumberFormat's Parse
To return a number from a text, we use parse method.
- Number parse(String source): Parses text from the beginning of the given string to produce a number.
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class CompactNumberFormatParse {
public static void main(String[] args) throws ParseException {
NumberFormat nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println("US/SHORT parsing:");
System.out.println(nf.parse("1K"));
System.out.println(nf.parse("1M"));
System.out.println(nf.parse("1B"));
nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.LONG);
System.out.println("\nUS/LONG parsing:");
System.out.println(nf.parse("1 thousand"));
System.out.println(nf.parse("1 million"));
System.out.println(nf.parse("1 billion"));
}
}
US/SHORT parsing: 1000 1000000 1000000000 US/LONG parsing: 1000 1000000 1000000000
The Locale as always will determine the parsing result (as in format result). Here the example if we use FR locale:
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class CompactNumberFormatParseFr {
public static void main(String[] args) throws ParseException {
NumberFormat nf = NumberFormat.getCompactNumberInstance(
Locale.FRANCE, NumberFormat.Style.SHORT);
System.out.println("FR/SHORT parsing:");
System.out.println("1K: " + nf.parse("1K"));
System.out.println("1 k: " + nf.parse("1 k"));
System.out.println("1M: " + nf.parse("1M"));
System.out.println("1 M: " + nf.parse("1 M"));
System.out.println("1B: " + nf.parse("1B"));
System.out.println("1 Md:" + nf.parse("1 Md"));
nf = NumberFormat.getCompactNumberInstance(
Locale.FRANCE, NumberFormat.Style.LONG);
System.out.println("\nFR/LONG parsing:");
System.out.println("1 thousand: " + nf.parse("1 thousand"));
System.out.println("1 mille: " + nf.parse("1 mille"));
System.out.println("1 million: " + nf.parse("1 million"));
System.out.println("1 billion: " + nf.parse("1 billion"));
System.out.println("1 milliard: " + nf.parse("1 milliard"));
}
}
FR/SHORT parsing: 1K: 1 1 k: 1000 1M: 1 1 M: 1000000 1B: 1 1 Md:1000000000 FR/LONG parsing: 1 thousand: 1 1 mille: 1000 1 million: 1000000 1 billion: 1000000000000 1 milliard: 1000000000
Note: The space character used in FR SHORT format is NO-BREAK SPACE (U+00A0) or character 160, not SPACE (U+0020) or character 32.
Parse with Grouping
By default 'grouping used' is set to 'false', this made default parsing behavior does not allow a grouping separator until 'grouping used' is set to true. To change 'grouping used' value, we can use method setGroupingUsed(boolean).
- void setGroupingUsed(boolean newValue): Set whether or not grouping will be used in this format.
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class CompactNumberFormatParseGrouping {
public static void main(String[] args) throws ParseException {
NumberFormat nf = NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println("Without Grouping:");
System.out.println(nf.parse("1,000K"));
System.out.println(nf.parse("1,000M"));
System.out.println(nf.parse("1,000B"));
nf.setGroupingUsed(true);
System.out.println("\nWith Grouping:");
System.out.println(nf.parse("1,000K"));
System.out.println(nf.parse("1,000M"));
System.out.println(nf.parse("1,000B"));
}
}
Without Grouping: 1 1 1 With Grouping: 1000000 1000000000 1000000000000