介绍Java的实用工具类库java.util包。在这个包中,Java提供了一些实用的方法和数据结构。例如,Java提供日期(Data)类、日历(Calendar)类来产生和获取日期及时间,提供随机数(Random)类产生各种类型的随机数,还提供了堆栈(Stack)、向量(Vector) 、位集合(Bitset)以及哈希表(Hashtable)等类来表示相应的数据结构。
6 o% T# l" p6 a* f
3 h# I; O% V5 y3 W; V2 ~图1.1给出了java.util包的基本层次结构图。下面我们将具体介绍其中几个重要的类。
3 D9 |- j; Y$ g' [' y: M
6 g# I4 O0 q. h/ r+ \, x ┌java.util.BitSet
0 Z/ s8 a2 `& s' e: L8 s5 @
│java.util.Calendar
9 [) g- ]. F6 }0 l$ E9 R1 b; Y( H' H │ └java.util.GregorianCalendar
# A& s6 M" \6 I9 e │java.util.Date
* Z) D, L9 V0 s& h │java.util.Dictionary
5 S3 L5 j1 }( e" r2 p2 n
│ └java.util.Hashtable
; o" ]0 e- x& O1 n& W │ └java.util.Properties
W+ R& l: {. V7 E0 J2 ? │java.util.EventObject
5 E- h$ |/ a8 h7 g! j │java.util.ResourceBundle
( b4 I! B! E. N0 ?$ j1 e& h: U
┌普通类┤ ├java.util.ListResourceBundle
~0 H, {# \( H3 x$ f* P │ │ └java.util.PropertyResourceBundle
0 r% `1 A( D1 y# `' B3 O
│ │java.util.Local
. e1 O+ Y% g- C9 C! Z. R( I5 X9 b │ │java.util.Observable
& _7 J7 b6 b& ?. A
│ │java.util.Random
3 [3 W# K& p0 {! z │ │java.util.StringTokenizer
6 w( w7 \) S9 w' l6 X& W
│ │java.util.Vector
- P) E6 Q6 M# e" N3 }+ b# N │ │ └java.util.Stack
7 u. Q6 t, A+ h9 i5 E$ q9 {+ f
Java.util┤ └java.util.TimeZone
- r1 ]3 y" V, p, c
│ └java.util.SimpleTimeZone
; f; Y$ Y" n/ x" c │ ┌java.util.Enumeration
1 i3 ?5 `; c4 Q+ x
├接 口┤java.util.EventListener
0 `$ h6 \: l6 U6 c* a │ └java.util.Observer
5 h# b2 y, W3 G8 D' x │ ┌java.util.EmptyStackException
" `/ ^# K; u. A( d1 F └异常类┤java.util.MissingResourceException
6 K6 c, [3 s" a: u6 T' D
│java.util.NoSuchElementException
+ ~# |% h1 G& a
└java.util.TooManyListenersException
- l; A8 H+ i* [, a1 O
4 G. K1 e2 @& Z7 w' G* m
图1.1 java.util包的基本层次结构
+ E+ \6 k7 Z- L3 i% K5 Z; E1 c6 e9 @1 D; q1 K
1.2 日期类Date1 Q7 P4 D2 R& E# F
6 I6 ^5 R$ i7 |- m1 k# |. R Java在日期类中封装了有关日期和时间的信息,用户可以通过调用相应的方法来获取系统时间或设置日期和时间。Date类中有很多方法在JDK1.0公布后已经过时了,在8.3中我们将介绍JDK1.0中新加的用于替代Date的功能的其它类。
4 l0 P6 e# s$ G% L! i, N 在日期类中共定义了六种构造函数。
: {" ?2 l1 ~$ u1 U7 m: M) i
(1)
public Date()2 z) [5 T# r( s+ U* ]
创建的日期类对象的日期时间被设置成创建时刻相对应的日期时间。
. V6 L. L: @! ?( v. @! a5 ]( R
例 Date today=new Date();//today被设置成创建时刻相对应的日期时间。
% L- J" i) h* J& y5 l4 z
6 U( p$ Z0 a0 w" s. L (2)
public Date (long date)7 \9 W; b! O! p/ V6 R+ v8 z
long 型的参数date可以通过调用Date类中的static方法parse(String s)来获得。
复制内容到剪贴板
代码:
long l=Date.parse("Mon 6 Jan 1997 13:3:00");
Date day=new Date(l);
//day中时间为1997年 1月6号星期一,13:3:00。(3)
public Date(String s)! Y& l9 T5 s2 d) i+ O+ K' k5 b
按字符串s产生一日期对象。s的格式与方法parse中字符串参数的模式相同。
复制内容到剪贴板
代码:
Date day=new Date("Mon 6 Jan 1997 13:3:00");
//day 中时间为1997年1月6号星期一,13:3:00.(4)
public Date(int year,int month,int date)
3 L. _! x, k9 t: W (5)
public Date(int year,int month,int date,int hrs,int min): c8 t( N% p1 r& U& ?, l' [
(6)
public Date(int year,int month,int date,int hrs,int min,int sec)! E! l( r6 i2 T9 o: A2 z2 u
按给定的参数创建一日期对象。
5 N1 w' }3 f+ W5 o: ?& @
参数说明:
6 m) ~* i4 L+ ^# W* g3 ^4 @5 a
year的值为:需设定的年份-1900。例如需设定的年份是1997则year的值应为97,即1997-1900的结果。所以Date中可设定的年份最小为1900;
4 b1 P# a$ S: u; F0 P" w9 i
month的值域为0~11,0代表1月,11表代表12月;
& b% m* {8 L/ T date的值域在1~31之间;
. [ x' p8 G( }; C, A, W
hrs的值域在0~23之间。从午夜到次日凌晨1点间hrs=0,从中午到下午1点间hrs=12;
% B% W5 h- L9 V* O
min和sec的值域在0~59之间。
复制内容到剪贴板
代码:
Date day=new Date(11,3,4);
//day中的时间为:04-Apr-11 12:00:00 AM另外,还可以给出不正确的参数。
# x' f& w) t0 v' ]7 S/ o设定时间为1910年2月30日,它将被解释成3月2日。
复制内容到剪贴板
代码:
Date day=new Date(10,1,30,10,12,34);
System.out.println("Day's date is:"+day);
//打印结果为:Day's date is:Web Mar 02 10:13:34 GMT+08:00 1910下面我们给出一些Date类中常用方法。
. {2 l6 H# U& j9 ?8 f# ~ (1)
public static long UTC(int year,int month,int date,int hrs. int min,int sec)6 n2 v! h: k0 r* }0 T0 Q+ n
该方法将利用给定参数计算UTC值。UTC是一种计时体制,与GMT(格林威治时间)的计时体系略有差别。UTC计时体系是基于原子时钟的,而GTMT计时体系是基于天文学观测的。计算中使用的一般为GMT计时体系。
1 k/ ~8 ]+ `4 g (2)
public static long parse(String s)
, p i& a) q$ a 该方法将字符串s转换成一个long型的日期。在介绍构造方法Date(long date)时曾使用过这个方法。
p- T/ d/ ` G* g/ H4 g 字符串s有一定的格式,一般为:(星期 日 年 时间GMT+时区)
0 a8 l/ V6 ?$ ?8 `9 p8 A+ D. d 若不注明时区,则为本地时区。
/ l4 ]* K n, b j$ y
(3)
public void setMonth(int month)# I( S! c2 C6 y1 J: D9 R+ N: x4 G
(4)
public int getMonth(). R8 ?9 j3 a e: L! x
这两个方法分别为设定和获取月份值。
+ x/ S, b& B3 k: }9 x
获取的月份的值域为0~11,0代表1月,11代表12月。
+ Z0 k& @% k% ?
(5)
public String toString()
- P- M! b2 e$ L. F+ B (6)
public String toLocalString()
0 n1 ^( ]" p2 r9 G' b8 u (7)
public String toGMTString()
' h9 [. J5 t% R: U* l% N 将给定日期对象转换成不同格式的字符串。它们对应的具体的格式可参看例子8.1。
7 c3 a" Z5 y7 o/ Y
(8)
public int getTimezoneOffset()
. q1 g# {) y; _& W 该方法用于获取日期对象的时区偏移量。
9 o; \% I! y" v: m+ v$ g% B6 o
例8.1中对上面介绍的Date类中的基本方法进行了具体的应用,并打印了相应的结果。由于使用了一些过时的方法,所以编译时会有警告信息。另外,由于本例中的时间表示与平台有关,不同的JDK版本对此处理不完全相同,因此不同版本的JDK执行本例的结果可能有细微差异。
复制内容到剪贴板
代码:
DateApp.java
import java.lang.System;
import java.util.Date;
public class DateApp{
public static void main(String args[]){
Date today=new Date();
//today中的日期被设成创建时刻的日期和时间,假设创建时刻为1997年3月
//23日17时51分54秒。
System.out.println("Today's date is "+today);
//返回一般的时间表示法,本例中结果为
//Today's date is Fri May 23 17:51:54 1997
System.out.println("Today's date(Internet GMT)is:"
+today.toGMTString());
//返回结果为GMT时间表示法,本例中结果为
//Today's date(Internet GMT)is: 23 May 1997 09:51:54:GMT
System.out.println("Today's date(Locale) is:"
+today.toLocaleString());
//返回结果为本地习惯的时间表示法,结果为
//Today's date(Locale)is:05/23/97 17:51:54
System.out.println("Today's year is: "+today.getYear());
System.out.println("Today's month is: "+(today.getMonth()+1));
System.out.println("Today's date is: "+today.getDate());
//调用Date类中方法,获取年月日的值。
//下面调用了不同的构造方法来创建Date类的对象。
Date day1=new Date(100,1,23,10,12,34);
System.out.println("Day1's date is: "+day1);
Date day2=new Date("Sat 12 Aug 1996 13:3:00");
System.out.println("Day2's date is: "+day2);
long l= Date.parse("Sat 5 Aug 1996 13:3:00 GMT+0800");
Date day3= new Date(l);
System.out.println("Day3's date(GMT)is: "+day3.toGMTString());
System.out.println("Day3's date(Locale)is: "
+day3.toLocaleString());
System.out.println("Day3's time zone offset is:"
+day3.getTimezoneOffset());
}
}运行结果
! {3 C% ^" e' b+ K7 C2 y3 ] k Today's date is Thu Dec 27 17:58:16 CST 2001
0 J* Y- p& T: _; n# D' [. ]
Today's date(Internet GMT)is:27 Dec 2001 09:58:16 GMT
# Y$ r7 D# m+ d Today's date(Locale) is:2001-12-27 17:58:16
! B: a+ u' ?$ |/ H1 N) h
Today's year is: 101
) C2 T8 H8 @ x" O
Today's month is: 12
% y J9 ?. c) b+ k/ D
Today's date is: 27
' q9 h2 v1 O! H3 n
Day1's date is: Wed Feb 23 10:12:34 CST 2000
# {" F3 a7 y' `1 U9 F0 r% m+ p Day2's date is: Fri Aug 12 13:03:00 CST 1996
) m9 ~/ I8 r7 b) r
Day3's date(GMT)is: 5 Aug 1996 05:03:00 GMT
- d% n0 ?& w" ]6 I
Day3's date(Locale)is: 1996-8-5 13:03:00
/ J0 v6 e5 N3 J
Day3's time zone offset is:-480
( m/ h% t" J. _9 d5 b) `+ v
5 `! H! v8 d: n" c- o& C
1.3 日历类Calendar
1 W) e p7 i* J2 k/ J! k
4 b' o4 a& R" O 在早期的JDK版本中,日期(Date)类附有两大功能:(1)允许用年、月、日、时、分、秒来解释日期:(2)允许对表示日期的字符串进行格式化和句法分析。在JDK1.1中提供了类Calendar来完成第一种功能,类DateFormat来完成第二项功能。dateFormat是java.text包中的一个类。与Date类有所不同的是,DateFormat类接受用各种语言和不同习惯表示的日期字符串。本节将介绍java.util包中的类Calendar及其它新增加的相关的类。
8 K+ \8 w% B# }7 c# I) Y$ I& F
类Calendar是一个抽象类,它完成日期(Date)类和普通日期表示法(即用一组整型域如YEAR,MONTH,DAY,HOUR表示日期)之间的转换。
4 h6 m4 T# b* j! o7 j2 ?
由于所使用的规则不同,不同的日历系统对同一个日期的解释有所不同。在JDK1.1中提供了Calendar类一个子类GregorianCalendar??它实现了世界上普遍使用的公历系统。当然用户也可以通过继承Calendar类,并增加所需规则,以实现不同的日历系统。
7 e1 T+ e% @# }8 ~3 ]% {) h( C 第GregorianCalendar继承了Calendar类。本节将在介绍类GregorianCalendar的同时顺带介绍Calendar类中的相关方法。
8 J; S# V: E$ {6 _$ w
类GregorianCalendar提供了七种构造函数:
9 Q9 j* C0 t# F (1)
public GregorianCalendar()
" z, `7 h) s5 N7 Y. u 创建的对象中的相关值被设置成指定时区,缺省地点的当前时间,即程序运行时所处的时区、地点的当前时间。
; }9 m$ G& W: Y( _* M (2)
public GregorianCalendar(TimeZone zone)
- y v& O2 M9 v! |" Y/ v! H5 Y" ~2 _+ y4 _ 创建的对象中的相关值被设置成指定时区zone,缺省地点的当前时间。
& e8 r- N. q0 x" @! |
(3)
public GregorianCalendar(Locale aLocale)
( O" z( c: @- n 创建的对象中的相关值被设置成缺省时区,指定地点aLocale的当前时间。
9 ]! d F0 H- T1 P* L6 ^" u
(4)
public GregorianCalendar(TimeZone zone,Local aLocale)3 E5 S. C; \1 ?& Y
创建的对象中的相关值被设置成指定时区,指定地点的当前时间。
' ?) b8 n" o( C( P: `
上面使用到的类TimeZone的性质如下:
7 ~0 J9 \1 d* e5 ~# [' W TimeZone是java.util包中的一个类,其中封装了有关时区的信息。每一个时区对应一组ID。类TimeZone提供了一些方法完成时区与对应ID两者之间的转换。
9 X3 r, Q x _; z9 V2 m (Ⅰ)已知某个特定的ID,可以调用方法
复制内容到剪贴板
代码:
public static synchronized TimeZone getTimeZone(String ID) ) |0 A* m$ v, t+ Q" Y* `& S6 `" ]
来获取对应的时区对象。
7 \7 ^+ J' z" e+ n$ p- n
例 太平洋时区的ID为PST,用下面的方法可获取对应于太平洋时区的时区对象:
复制内容到剪贴板
代码:
TimeZone tz=TimeZone.getTimeZone("PST");
4 i1 j8 P% D# { 调用方法getDefault()可以获取主机所处时区的对象。
复制内容到剪贴板
代码:
TimeZone tz=TimeZone.getDefault();(Ⅱ)调用以下方法可以获取时区的ID
+ p! E! K1 B6 v% y
■
public static synchronized String[] getavailableIDs(int rawOffset)
; b. M+ \! q. Z9 }* z 根据给定时区偏移值获取ID数组。同一时区的不同地区的ID可能不同,这是由于不同地区对是否实施夏时制意见不统一而造成的。
; P4 H \% N2 m2 v4 V 例
复制内容到剪贴板
代码:
String s[]=TimeZone.getAvailableIDs(-7*60*60*1000); 打印s,结果为s[0]=PNT,s[1]=MST
0 y' s8 o$ o2 s9 {3 p ■
public static synchronized String[] getAvailableIDs()
7 S/ d% K1 _# P% C# E7 l! i 获取提供的所有支持的ID。
, y8 r" j E+ h/ Z9 E: U" a
■
public String getID()
& x' ]1 t8 s0 S$ _1 y 获取特定时区对象的ID。
复制内容到剪贴板
代码:
TimeZone tz=TimeZone.getDefault();
String s=tz.getID(); 打印s,结果为s=CTT。
6 ]$ `, y" }* g, ?" y9 v* a9 w6 y
上面使用类的对象代表了一个特定的地理、政治或文化区域。Locale只是一种机制,它用来标识一类对象,Local本身并不包含此类对象。
x( d% }/ ]0 P; O 要获取一个Locale的对象有两种方法:
! o1 {* ?3 G3 Z, Z7 A4 {
(Ⅰ)调用Locale类的构造方法
' G, r4 R8 [$ B. w5 z. ]& c
Locale(String language,String country)
3 I# i- u7 T1 k( w8 e/ n9 M- b Locale(String language,String country,String variant)
1 J3 h/ E* e4 a' H2 k7 I/ e0 r
参数说明:language??在ISO-639中定义的代码,由两个小写字母组成。
: N$ j1 O, }# B0 K7 Z2 ` country??在ISO-3166中定义的代码,由两个大写字母组成。
6 h5 r. E/ `7 Z; V1 d8 g! x q8 q# K variant??售货商以及特定浏览器的代码,例如使用WIN代表Windows。
l. ^1 d$ I i# ]5 u
(Ⅱ)调用Locale类中定义的常量
* F9 J6 ~+ [" q
Local类提供了大量的常量供用户创建Locale对象。
- a4 B" X2 q& X8 @! w3 `$ P
例 Locale.CHINA
% C: a0 A$ x; O* e: r; J i 为
中国创建一个Locale的对象。
' a7 F) X9 A! V( |+ |3 z: w' v
类TimeZone和类Locale中的其它方法,读者可查阅API。
1 U$ |) ]# l5 U" e (5)
public GregorianCalendar(int year,int month,int date)6 b9 x1 a4 R! u' A3 D; h+ a q
(6)
public GregorianCalendar(int year,int month,int date,int hour,int minute)% i& v$ [( u+ Y; R& S3 s1 y
(7)
public GregorianCalendar(int year,int month,int date,int hour,int minute,int second)
1 _1 x% E" I. m# K E 用给定的日期和时间创建一个GregorianCalendar的对象。
1 I/ c }% w8 V- L
参数说明:
3 H) m3 s2 q4 s3 |5 N
year-设定日历对象的变量YEAR;month-设定日历对象的变量MONTH;
$ C1 s; n* g5 W7 D" C) a6 J
date-设定日历对象的变量DATE;hour-设定日历对象的变量HOUR_OF_DAY;
- w# M e! F+ q' v* B
minute-设定日历对象的变量MINUTE;second-设定日历对象的变量SECOND。
3 e: F- [; v" W9 }0 ], Z+ R: ~ 与Date类中不同的是year的值没有1900这个下限,而且year的值代表实际的年份。month的含义与Date类相同,0代表1月,11代表12月。
复制内容到剪贴板
代码:
GregorianCalendar cal=new GregorianCalendar(1991,2,4) cal的日期为1991年3月4号。
% z& e3 w! t9 y
除了与Date中类似的方法外,Calendar类还提供了有关方法对日历进行滚动计算和数学计算。计算规则由给定的日历系统决定。进行日期计算时,有时会遇到信息不足或信息不实等特殊情况。Calendar采取了相应的方法解决这些问题。当信息不足时将采用缺省设置,在GregorianCalendar类中缺省设置一般为YEAR=1970,MONTH=JANUARY,DATE=1。
! |3 O" y- r# t" I' p 当信息不实时,Calendar将按下面的次序优先选择相应的Calendar的变量组合,并将其它有冲突的信息丢弃。
2 V) e+ d/ T! ~0 Z( A
MONTH+DAY_OF_MONTH
0 n2 ]& R1 O/ _/ s- S7 ~
MONTH+WEEK_OF_MONTH+DAY_OF_WEEK
7 W, n, `+ E2 e# o$ _
MONTH+DAY_OF_WEEK_OF_MONTH+DAY_OF_WEEK
0 u; s U/ I* d5 j6 N( W
DAY_OF+YEAR
% i1 K- B* e# T2 }; F8 r DAY_OF_WEEK_WEEK_OF_YEAR
' k% G- }: U6 f( a& D% s
HOUR_OF_DAY
- Z0 \$ N- c# c
, o1 M$ @% y3 S! Y5 B- B6 k1.4 随机数类Random
! R. ~2 Z# y P, E! O: I
$ C7 o R' E- t3 u; W! ^! [$ H Java实用工具类库中的类java.util.Random提供了产生各种类型随机数的方法。它可以产生int、long、float、double以及Goussian等类型的随机数。这也是它与java.lang.Math中的方法Random()最大的不同之处,后者只产生double型的随机数。
) B* k: L$ k5 l% \
类Random中的方法十分简单,它只有两个构造方法和六个普通方法。
1 Z% W, ]5 h+ y+ S 构造方法:
+ y5 T% r. L) m% F" Y (1)
public Random()1 H$ W2 b5 `% l; j2 }
(2)
public Random(long seed), e3 u. J% k! m; K& [4 G/ }! p
Java产生随机数需要有一个基值seed,在第一种方法中基值缺省,则将系统时间作为seed。
~% P4 `( o7 w6 C' g* `# |& r4 z 普通方法:
- [& l4 v/ B) q+ r% \$ ?$ ], B (1)
public synonronized void setSeed(long seed)
2 b1 k; q/ h8 K; Z% @) | 该方法是设定基值seed。
# c! x; ?! D- p: ?8 B- X0 K0 ~
(2)
public int nextInt()
7 k+ e5 S) H9 A- L6 r" n2 U 该方法是产生一个整型随机数。
* O1 C9 L9 @: @' U7 f K (3)
public long nextLong()5 ^$ u' D4 E$ P( W
该方法是产生一个long型随机数。
5 Y w+ m& `' d# E2 ~
(4)
public float nextFloat()
! W* [# L& C1 J( Y0 f9 ?8 \ 该方法是产生一个Float型随机数。
; ^; x2 `$ D2 ` P5 t5 ?
(5)
public double nextDouble()8 |8 i. r9 C# c V- {/ ]
该方法是产生一个Double型随机数。
6 g) z9 [. j& G9 m" D
(6)
public synchronized double nextGoussian()' g# w" ^& w2 F
该方法是产生一个double型的Goussian随机数。
! @! c4 n) E0 X: w例1.2 RandomApp.java。
复制内容到剪贴板
代码:
import java.util.Random;
public class RandomApp{
public static void main(String args[]){
Random ran1=new Random();
Random ran2=new Random(12345);
//创建了两个类Random的对象。
System.out.println("The 1st set of random numbers:");
System.out.println("\t Integer:"+ran1.nextInt());
System.out.println("\t Long:"+ran1.nextLong());
System.out.println("\t Float:"+ran1.nextFloat());
System.out.println("\t Double:"+ran1.nextDouble());
System.out.println("\t Gaussian:"+ran1.nextGaussian());
//产生各种类型的随机数
System.out.print("The 2nd set of random numbers:");
for(int i=0;i<5;i++){
System.out.println(ran2.nextInt()+" ");
if(i==2) System.out.println();
//产生同种类型的不同的随机数。
System.out.println();//原文如此
}
}
}运行结果:
: O4 k7 `- f9 Q& P' W# ^- C0 ]% F
The 1st set of random numbers:
0 ]. |( E# p% ]% [) `3 \
Integer:-173899656
- W" S _9 Y% R* C
Long:8056223819738127077
& t! T/ {$ i- N M6 L
Float:0.6293638
! @- B0 q- q/ ~ E0 i8 n Double:0.7888394520265607
# [6 Q. V' G2 V9 M( B9 q Gaussian:0.5015701094568733
4 B, w3 u9 G0 s& d
The 2nd set of random numbers:1553932502
' r B# e) d6 s7 Y8 c; B1 E -2090749135
, s& R/ d, ^9 W -287790814
6 Z, e; _5 O1 C
-355989640
7 d$ ~, r. z- k( e; d+ Z5 X2 e -716867186