Java Format 格式化

Posted zohnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Format 格式化相关的知识,希望对你有一定的参考价值。


Format

该类是个抽象基类,具体子类必须实现:

//将对象格式化为指定模式的字符串
format(Object obj, StringBuffer toAppendTo, FieldPosition pos)

//将字符串重新解析为对象 
parseObject(String source, ParsePosition pos)

DateFormat(格式化日期时间)

DateFormat根据当前语言环境格式化日期和时间。

DateFormat是一个抽象类,所以不能直接new创建实例对象。但该类为我们提供了工厂方法方便我们使用。

  • getDateInstance() ——获取格式化的日期:2015-2-12
  • getTimeInstance() ——获取格式化的时间:23:33:33
  • getDateTimeInstance() ——获取格式化的日期和时间:2015-2-12
  • getInstance() ——获取格式化的日期和时间:15-2-12 下午11:33

也许你会发现,在这些工厂发放中允许我们传入一个int参数,该参数允许我们设定格式化风格,从而得到我们相对理想的结果。下表中对应了不同的style值和输出样式(这些常量值都在DateFormat类中)

样式值 日期 时间
SHORT 17-12-22 上午09:00
MEDIUM 2017-12-22 09:00:00
LONG 2015年12月22日 上午09时00分00秒
FULL 2015年12月22日 星期二 上午09时00分00秒 CST
DEFAULT 2015-12-22 09:00:00

当然你也可以指定语言环境获取该语言环境下的格式化日期和时间

//获取加拿大的格式化日期
DateFormat format = DateFormat.getDateInstance(DateFormat.DEFAULT,Locale.CANADA);

SimpleDateFormat

SimpleDateFormat是DateFormat的一个具体类,它允许我们指定格式模式从而获取我们理想的格式化日期和时间。

通过构造方法可以传入一个自定义格式的日期和时间
对于格式模式字符串,API为我们提供了丰富的模式元素,下面列出几个常用的模式元素

字母 日期或时间元素 示例
y 2015
M 年中的月份 12
w 年中的周数 50
W 月份中的周数 02
D 年中的天数 344
d 月份中的天数 10
F 月份中的星期 02
E 星期中的天数 星期四、Thu
a AM/PM标记 下午、PM
H 一天中的小时数(0~23) 21
k 一天中的小时数(1~24) 21
K am/pm中的小时数(0~11) 09
h am/pm中的小时数(1~12) 09
m 小时中的分钟数 31
s 分钟中的秒数 08
S 毫秒数 716

如果你设置Locale的话,会有不同的显示格式,比如如果设置Locale.ENGLISH,E会显示为英文格式,a显示为AM或PM

Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("今天是yyyy-MM-dd E hh:mm:ss,是yyyy年的第DD天,在该月是第dd天");

System.out.println(format.format(date));

将会输出:今天是2015-12-10 星期四 09:38:16,是2015年的第344天,在该月是第10天




NumberFormat(格式化数字)

NumberFormat根据当前语言环境格式化数字
NumberFormat同样是一个抽象基类,可以使用API中的工厂方法获取实例对象

  • getCurrencyInstance() ——根据语言环境获取货币数值格式
  • getInstance() ——获取常规数值格式
  • getIntegetInstance() ——获取整数值格式,如果是小数则会四舍五入
  • getPercentInstance() ——获取百分比数值格式

DecimalFormat(子类)

DecimalFormat同SimpleDateFormat类似,允许我们指定格式模式获取我们想要的格式化数值

DecimalFormat类对于数值的小数部分,默认显示3位小数,在去掉超出小数点后面3位的部分时,会将数值四舍五入为最接近的数值格式化输出。当然我们可以对这个默认进行设置

  • DecimalFormat() ——获取自定义格式化数值
    (对于小数部分,默认显示3位小数,超过则四舍五入)
  • setMaximumFractionDigits( int ) ——设置小数部分允许显示的最大数位
  • setMinimumFractionDigits( int ) ——设置小数部分允许显示的最小数位,如果不够就补零
标识 含义
0 表示一个数字,被格式化数值不够的位数会补0
# 表示一个数字,被格式化数值不够的位数会忽略
. 小数点分隔符的占位符
, 分组分隔符的占位符
- 缺省负数前缀
% 将数值乘以100并显示为百分数
\u2030 将数值乘以1000并显示为千分数
DecimalFormat format1 = new DecimalFormat("#\u2030");
System.out.println(format1.format(0.3345));
//输出334‰

DecimalFormat format2 = new DecimalFormat("##.##");
System.out.println(format2.format(12.345));
//输出12.35

DecimalFormat format3 = new DecimalFormat("0000.00");
System.out.println(format3.format(12.345));
//输出0012.35

DecimalFormat format4 = new DecimalFormat("#.##%");
System.out.println(format4.format(12.345));
//输出1234.5%




ChoiceFormat

允许将格式化运用到某个范围的数,通常与MessageFormat一同使用。ChoiceFormat在构造方法中接收一个format数组和一个limits数组,这两个数组的长度必须相等,例如:

limits = 1,2,3,4,5,6,7
formats = "Sun","Mon","Tue","Wed","Thur","Fri","Sat"

limits数组实际上是个区间,可开可闭,并且必须按升序排列,如果不按升序排列,格式化结果将会不正确,还可以使用\u221E(表示无穷大)。
ChoiceFormat的匹配公式

limit[j] <= X <limit[j+1]

其中X表示使用format方法传入的值,j表示limit数组中的索引。当且仅当上述公式成立时,X匹配j,如果不能匹配,则会根据X是太小还是太大,匹配limits数组的第一个索引或最后一个索引,然后使用匹配的limits数组中的索引,去formats数组中寻找相同索引的值。例子:

double[] limits =  3, 4, 5, 6, 7, 8, 9 ;
String[] formats =  "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" ;
ChoiceFormat format = new ChoiceFormat(limits, formats);
System.out.println(format.format(2.5));//将会输出"星期一"
/**3.6介于3和4之间,所以会匹配3,又由于3在limits数组中的索引是0,所以会在formats数组徐照索引0的值,即输出"星期一"
*/
System.out.println(format.format(3.6));

下面看一下ChoiceFormat类中的几个常用方法

  • nextDouble(double d) ——查找大于d的最小double值,用在limits数组中,从而使limits数组形成一个右开区间数组,例如

    limits = 0,1,ChoiceFormat.nextDouble(1)

  • nextDouble(double d, boolean positive) ——如果positive参数为true,表示查找大于d的最小double值;如果positive参数为false,表示查找小于d的最大double值,这样就可以使limits形成一个左开区间数组。
  • previousDouble(double d) ——查找小于d的最大double值

ChoiceFormat类的构造方法也允许我们传入一个模式字符串,format方法会根据这个模式字符串执行格式化操作。一个模式元素的格式如下:

doubleNum [占位符] formatStr

占位符可以使用#、< 、\u2264(<=)

ChoiceFormat cf = new ChoiceFormat("1#is 1 | 1<is more than 1");
System.out.println(cf.format(1));//输出"is 1"
System.out.println(cf.format(2));//输出"is more than 1"
System.out.println(cf.format(0));//输出"is 1"

由上面的例子可以看出,模式字符串中的每个模式元素之间使用"|"分割,"|"前后可以添加空格以美化代码,而且必须按照升序进行书写,否则会出现java.lang.IllegalArgumentException的运行时异常。

观看ChoiceFormat类的源码我们得知,实际上在内部,模式字符串还是被转换为limits和formats两个数组。在源码中

public ChoiceFormat(String newPattern)  
     applyPattern(newPattern);

/** applyPattern(newPattern)方法的部分源码
*/
public void applyPattern(String newPattern) 
    ...
    choiceLimits = new double[count];
    System.arraycopy(newChoiceLimits, 0, choiceLimits, 0, count);
    choiceFormats = new String[count];
    System.arraycopy(newChoiceFormats, 0, choiceFormats, 0, count);
    ...

可以看出ChoiceFormat(String newPattern)调用了applyPattern(String newPattern)方法,在applyPattern方法中对newPattern字符串进行解析,然后将解析后的数据放置到ChoiceFormat类的两个私有属性double[] choiceLimits和String[] choiceFormats中,然后使用格式化方法即可。




MessageFormat

MessageFormat提供了以语言环境无关的生成连接消息的方式。

常用MessageFormat的静态方法format,该方法接收一个字符串的模式和一组对象(对象数组),按照模式形式将格式化的对象插入到模式中,然后返回字符串结果。

MessageFormat的格式模式元素(FormatElement)形式如下:

  • ArgumentIndex
  • ArgumentIndex,FormatType
  • ArgumentIndex,FormatType,FormatStyle

其中ArgumentIndex对象数组中的索引,从0开始,
FormatType包括number、date、 time、choice,
FormatStyle包括short、medium、long、full、integer、currency、percent、SubformatPattern(子模式),

在MessageFormat类的内部,FormatType和FormatStyle实际上是创建格式元素的Format示例
number对应了NumberFormat,其子格式对应了DecimalFormat
date和time对应了DateFormat,其资格是对应了SimpleDateFormat
choice对应了ChoiceFormat

你可以直接使用MessageFormat类中的静态方法format,像这样:

/**这是源码注释中的一个例子
* 在这个例子中静态方法format第一个参数是字符串类型的,
* 即模式字符串,第二个参数是个可变参数,实际上就是一个Object类型的数组。
* 在模式字符串中使用""标识一个FormatElement。""中的ArgumentIndex对应Object数组中响应索引处的值。
*/
int planet = 7;
String event = "a disturbance in the Force";
String result = MessageFormat.format("At 1,time on 1,date, there was 2 on planet 0,number,integer.",
                  planet, new Date(), event);
System.out.println(result);
//输出:At 20:39:15 on 2015-12-11, there was a disturbance in the Force on planet 7.

你也可以使用MessageFormat的构造方法传入pattern string(模式字符串),然后调用普通的format方法,在这里就不举栗子了。

我们不仅被允许使用MessageFormat类中提供默认的FormatElement去format这些对象,还可以设置自己的Format对象format这些Object。

/**在这个例子中,MessageFormat和ChoiceFormat被结合使用
* MessageFormat类中有3个方法值的我们关注
* 1.setFormatByArgumentIndex(int argumentIndex, Format newFormat)//
* 2.setFormats(Format[] newFormats)
* 3.setFormat(int formatElementIndex, Format newFormat)
* 在这个例子当中,在MessageFormat的模式字符串的FormatElement(即中的内容)中
* 索引为0的地方将使用ChoiceFormat的格式去格式化。
* 如果在set的Format中仍具有FormatElement,则会递归调用MessageFormat的format方法。
*/
MessageFormat form = new MessageFormat("The disk \"1\" contains 0.");
double[] filelimits =  0, 1, 2 ;
String[] filepart =  "no files", "one file", "0,number files" ;
ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
form.setFormatByArgumentIndex(0, fileform);
int fileCount = 1273;
String diskName = "MyDisk";
Object[] testArgs =  new Long(fileCount), diskName ;
System.out.println(form.format(testArgs));
//输出:The disk "MyDisk" contains 1,273 files.




StringFormat(字符串格式化)

format方法使用占位符进行格式化
常规类型、字符类型和数值类型的占位符格式:

%[index$][标识][最小宽度][.精度]转换符

日期和时间类型的占位符格式:

%[index$][标识][最小宽度]转换符

与参数不对应的占位符格式:

%[标识][最小宽度]转换符

其中index表示参数列表中的位置上的值

可用标识:

标识 含义
- 在最小宽度内左对齐,不可与0标识一起使用
0 若内容长度不足最小宽度,则在左边用0来填充
# 对8进制和16进制,8进制前添加一个0,16进制前添加0x
+ 结果总包含一个+或-号
空格 正数前加空格,负数前加-号
, 只用与十进制,每3位数字间用,分隔
( 若结果为负数,则用括号括住,且不显示符号

可用转换符:
转换符 | 含义
:-: | :-:
b | 布尔类型,只要实参为非false的布尔类型,均格式化为字符串true,否则为字符串false
n | 平台独立的换行符, 也可通过System.getProperty("line.separator")获取
f | 浮点数型(十进制)。显示9位有效数字,且会进行四舍五入。如99.99
a | 浮点数型(十六进制)
e | 指数类型。如9.38e+5
g | 浮点数型(比%f,%a长度短些,显示6位有效数字,且会进行四舍五入)
s | 字符串类型
c | 字符类型

String.format("小明%d岁,住在%s,月工资有%.2f", 25,"北京市",6633.435);
输出:小明今年25岁,他住在北京市,他的月工资有6633.44

double num = 123.4567899;
String result2 = String.format("%e", num);
输出:1.234568e+02

总结

  1. Format中的子类都是不同步,所以需要注意线程安全问题
  2. 学习最重要的是多去尝试,多编写代码测试




以上是关于Java Format 格式化的主要内容,如果未能解决你的问题,请参考以下文章

JAVA字符串格式化-String.format()的使用

JAVA字符串格式化-String.format()的使用

JAVA字符串格式化-String.format()的使用

JAVA字符串格式化-String.format()的使用

JAVA字符串格式化-String.format()的使用

JAVA字符串格式化-String.format()的使用