Java 12 extends existing number formatting APIs to provide support for locale-sensitive compact number formatting.
Now numbers like 1000 (for example) can be formatted as "1K" (short style) or "1 thousand" (long style).
New class CompactNumberFormat
CompactNumberFormat is a concrete subclass of NumberFormat that formats a decimal number in its compact form.
This class is based on SPI pattern. That means we don't need to directly use this class but instead we can get its instance via new factory methods of NumberFormat .
New enum NumberFormat.Style
This enum represents the style for formatting a number within a given NumberFormat instance
public enum Style {
SHORT,
LONG
}
Obtaining CompactNumberFormat instance
Following new factory methods of NumberFormat can be used to obtain CompactNumberFormat instance:
package java.text;
.......
public abstract class NumberFormat extends Format {
.......
//Returns a compact number format for the default Locale with NumberFormat.Style#SHORT
public static NumberFormat getCompactNumberInstance() {......}
//Returns a compact number format for the specified Locale and NumberFormat.Style
public static NumberFormat getCompactNumberInstance(Locale locale, NumberFormat.Style formatStyle) {.....}
......
}
Examples
Compact Formatting
package com.logicbig.example;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import java.util.stream.IntStream;
public class CompactNumberFormatExample {
public static void main(String[] args) {
formatForLocale(Locale.US);
formatForLocale(Locale.GERMANY);
}
private static void formatForLocale(Locale locale) {
List<Integer> numbers = List.of(1000, 1000000, 1000000000);
System.out.printf("-- SHORT format for locale=%s --%n", locale);
numbers.stream().forEach((num) -> {
NumberFormat nf = NumberFormat.getCompactNumberInstance(locale, NumberFormat.Style.SHORT);
String format = nf.format(num);
System.out.println(format);
});
System.out.printf("-- LONG format for locale=%s --%n", locale);
numbers.stream().forEach((num) -> {
NumberFormat nf = NumberFormat.getCompactNumberInstance(locale, NumberFormat.Style.LONG);
String format = nf.format(num);
System.out.println(format);
});
}
}
-- SHORT format for locale=en_US --
1K
1M
1B
-- LONG format for locale=en_US --
1 thousand
1 million
1 billion
-- SHORT format for locale=de_DE --
1.000
1 Mio.
1 Mrd.
-- LONG format for locale=de_DE --
1 Tausend
1 Million
1 Milliarde
Formatting with Rounding
By default RoundingMode.HALF_EVEN is used:
package com.logicbig.example;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
public class CompactNumberFormatDefaultRounding {
public static void main(String[] args) {
formatForLocale(Locale.US);
}
private static void formatForLocale(Locale locale) {
List<Integer> numbers = List.of(1500, 1500000, 1200000000);
System.out.printf("-- SHORT format for locale=%s --%n", locale);
numbers.stream().forEach((num) -> {
NumberFormat nf = NumberFormat.getCompactNumberInstance(locale, NumberFormat.Style.SHORT);
String format = nf.format(num);
System.out.println(format);
});
System.out.printf("-- LONG format for locale=%s --%n", locale);
numbers.stream().forEach((num) -> {
NumberFormat nf = NumberFormat.getCompactNumberInstance(locale, NumberFormat.Style.LONG);
String format = nf.format(num);
System.out.println(format);
});
}
}
-- SHORT format for locale=en_US -- 2K 2M 1B -- LONG format for locale=en_US -- 2 thousand 2 million 1 billion
We can set rounding mode by calling NumberFormat.setRoundingMode(RoundingMode) :
package com.logicbig.example;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
public class CompactNumberFormatExplicitRounding {
public static void main(String[] args) {
formatForLocale(Locale.US);
}
private static void formatForLocale(Locale locale) {
List<Integer> numbers = List.of(1500, 1500000, 1200000000);
System.out.printf("-- SHORT format for locale=%s --%n", locale);
numbers.stream().forEach((num) -> {
NumberFormat nf = NumberFormat.getCompactNumberInstance(locale, NumberFormat.Style.SHORT);
nf.setRoundingMode(RoundingMode.HALF_DOWN);
String format = nf.format(num);
System.out.println(format);
});
System.out.printf("-- LONG format for locale=%s --%n", locale);
numbers.stream().forEach((num) -> {
NumberFormat nf = NumberFormat.getCompactNumberInstance(locale, NumberFormat.Style.LONG);
nf.setRoundingMode(RoundingMode.HALF_DOWN);
String format = nf.format(num);
System.out.println(format);
});
}
}
-- SHORT format for locale=en_US -- 1K 1M 1B -- LONG format for locale=en_US -- 1 thousand 1 million 1 billion
Parsing
package com.logicbig.example;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class CompactNumberFormatParseExample {
public static void main(String[] args) throws ParseException {
NumberFormat nf = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
System.out.println("-- short compact parsing --");
Number num = nf.parse("1K");
System.out.println(num);
num = nf.parse("1M");
System.out.println(num);
num = nf.parse("1B");
System.out.println(num);
System.out.println("-- long compact parsing --");
nf = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.LONG);
num = nf.parse("1 thousand");
System.out.println(num);
num = nf.parse("1 million");
System.out.println(num);
num = nf.parse("1 billion");
System.out.println(num);
}
}
-- short compact parsing -- 1000 1000000 1000000000 -- long compact parsing -- 1000 1000000 1000000000
Parsing with grouping
The default parsing behavior does not allow a grouping separator until 'grouping used' is set to true by using setGroupingUsed(boolean) . By default 'grouping used' is set to 'false'.
package com.logicbig.example;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class CompactNumberFormatParseWithGrouping {
public static void main(String[] args) throws ParseException {
parseWithGrouping(false);
parseWithGrouping(true);
}
private static void parseWithGrouping(boolean grouping) throws ParseException {
System.out.printf("-- grouping=%s ---%n", grouping);
NumberFormat nf = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
nf.setGroupingUsed(grouping);
Number num = nf.parse("1,00K");
System.out.println(num);
num = nf.parse("1,00M");
System.out.println(num);
num = nf.parse("1,00B");
System.out.println(num);
}
}
-- grouping=false --- 1 1 1 -- grouping=true --- 100000 100000000 100000000000
Example ProjectDependencies and Technologies Used: |