java.util包详解 您所在的位置:网站首页 java怎么导入所有包里 java.util包详解

java.util包详解

2023-12-23 01:00| 来源: 网络整理| 查看: 265

介绍Java的实用工具类库java.util包。在这个包中,Java提供了一些实用的方法和数据结构。本章介绍Java的实用工具类库java.util包。在这个包中,Java提供了一些实用的方法和数据结构。例如,Java提供日期(Data)类、日历(Calendar)类来产生和获取日期及时间,提供随机数(Random)类产生各种类型的随机数,还提供了堆栈(Stack)、向量(Vector) 、位集合(Bitset)以及哈希表(Hashtable)等类来表示相应的数据结构。  图8.1给出了java.util包的基本层次结构图。下面我们将具体介绍其中几个重要的类。           ┌java.util.BitSet           │java.util.Calendar           │      └java.util.GregorianCalendar           │java.util.Date           │java.util.Dictionary           │      └java.util.Hashtable           │             └java.util.Properties           │java.util.EventObject           │java.util.ResourceBundle       ┌普通类┤      ├java.util.ListResourceBundle       │   │      └java.util.PropertyResourceBundle       │   │java.util.Local       │   │java.util.Observable       │   │java.util.Random       │   │java.util.StringTokenizer       │   │java.util.Vector       │   │      └java.util.Stack  Java.util┤   └java.util.TimeZone       │          └java.util.SimpleTimeZone       │   ┌java.util.Enumeration       ├接 口┤java.util.EventListener       │   └java.util.Observer       │   ┌java.util.EmptyStackException       └异常类┤java.util.MissingResourceException           │java.util.NoSuchElementException           └java.util.TooManyListenersException       图8.1 java.util包的基本层次结构8.2 日期类Date  Java在日期类中封装了有关日期和时间的信息,用户可以通过调用相应的方法来获取系统时间或设置日期和时间。Date类中有很多方法在JDK1.0公布后已经过时了,在8.3中我们将介绍JDK1.0中新加的用于替代Date的功能的其它类。  在日期类中共定义了六种构造函数。  (1)public Date()  创建的日期类对象的日期时间被设置成创建时刻相对应的日期时间。  例 Date today=new Date();//today被设置成创建时刻相对应的日期时间。  (2)public Date (long date)  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)  按字符串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)  (5)public Date(int year,int month,int date,int hrs,int min)  (6)public Date(int year,int month,int date,int hrs,int min,int sec)  按给定的参数创建一日期对象。  参数说明:  year的值为:需设定的年份-1900。例如需设定的年份是1997则year的值应为97,即1997-1900的结果。所以Date中可设定的年份最小为1900;  month的值域为0~11,0代表1月,11表代表12月;  date的值域在1~31之间;  hrs的值域在0~23之间。从午夜到次日凌晨1点间hrs=0,从中午到下午1点间hrs=12;  min和sec的值域在0~59之间。  例 Date day=new Date(11,3,4);  //day中的时间为:04-Apr-11 12:00:00 AM另外,还可以给出不正确的参数。  例 设定时间为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类中常用方法。  (1)public static long UTC(int year,int month,int date,int hrs. int min,int sec)  该方法将利用给定参数计算UTC值。UTC是一种计时体制,与GMT(格林威治时间)的计时体系略有差别。UTC计时体系是基于原子时钟的,而GTMT计时体系是基于天文学观测的。计算中使用的一般为GMT计时体系。  (2)public static long parse(String s)  该方法将字符串s转换成一个long型的日期。在介绍构造方法Date(long date)时曾使用过这个方法。  字符串s有一定的格式,一般为:  (星期 日 年 时间GMT+时区)  若不注明时区,则为本地时区。  (3)public void setMonth(int month)  (4)public int getMonth()  这两个方法分别为设定和获取月份值。  获取的月份的值域为0~11,0代表1月,11代表12月。  (5)public String toString()  (6)public String toLocalString()  (7)public String toGMTString()  将给定日期对象转换成不同格式的字符串。它们对应的具体的格式可参看例子8.1。  (8)public int getTimezoneOffset()  该方法用于获取日期对象的时区偏移量。  例8.1中对上面介绍的Date类中的基本方法进行了具体的应用,并打印了相应的结果。由于使用了一些过时的方法,所以编译时会有警告信息。另外,由于本例中的时间表示与平台有关,不同的JDK版本对此处理不完全相同,因此不同版本的JDK执行本例的结果可能有细微差异。  例8.1 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());   }  }  运行结果(JDK1.3版,与原文不同,原文是JDK1.0版):  E:/java/tutorial/java01>java DateApp  Today's date is Thu Dec 27 17:58:16 CST 2001  Today's date(Internet GMT)is:27 Dec 2001 09:58:16 GMT  Today's date(Locale) is:2001-12-27 17:58:16  Today's year is: 101  Today's month is: 12  Today's date is: 27  Day1's date is: Wed Feb 23 10:12:34 CST 2000  Day2's date is: Fri Aug 12 13:03:00 CST 1996  Day3's date(GMT)is: 5 Aug 1996 05:03:00 GMT  Day3's date(Locale)is: 1996-8-5 13:03:00  Day3's time zone offset is:-480  E:/java/tutorial/java01>8.3 日历类Calendar  在早期的JDK版本中,日期(Date)类附有两大功能:(1)允许用年、月、日、时、分、秒来解释日期:(2)允许对表示日期的字符串进行格式化和句法分析。在JDK1.1中提供了类Calendar来完成第一种功能,类DateFormat来完成第二项功能。dateFormat是java.text包中的一个类。与Date类有所不同的是,DateFormat类接受用各种语言和不同习惯表示的日期字符串。本节将介绍java.util包中的类Calendar及其它新增加的相关的类。  类Calendar是一个抽象类,它完成日期(Date)类和普通日期表示法(即用一组整型域如YEAR,MONTH,DAY,HOUR表示日期)之间的转换。  由于所使用的规则不同,不同的日历系统对同一个日期的解释有所不同。在JDK1.1中提供了Calendar类一个子类GregorianCalendar??它实现了世界上普遍使用的公历系统。当然用户也可以通过继承Calendar类,并增加所需规则,以实现不同的日历系统。  第GregorianCalendar继承了Calendar类。本节将在介绍类GregorianCalendar的同时顺带介绍Calendar类中的相关方法。  类GregorianCalendar提供了七种构造函数:  (1)public GregorianCalendar()  创建的对象中的相关值被设置成指定时区,缺省地点的当前时间,即程序运行时所处的时区、地点的当前时间。  (2)public GregorianCalendar(TimeZone zone)  创建的对象中的相关值被设置成指定时区zone,缺省地点的当前时间。  (3)public GregorianCalendar(Locale aLocale)  创建的对象中的相关值被设置成缺省时区,指定地点aLocale的当前时间。  (4)public GregorianCalendar(TimeZone zone,Local aLocale)  创建的对象中的相关值被设置成指定时区,指定地点的当前时间。  上面使用到的类TimeZone的性质如下:  TimeZone是java.util包中的一个类,其中封装了有关时区的信息。每一个时区对应一组ID。类TimeZone提供了一些方法完成时区与对应ID两者之间的转换。  (Ⅰ)已知某个特定的ID,可以调用方法  public static synchronized TimeZone getTimeZone(String ID)来获取对应的时区对象。  例 太平洋时区的ID为PST,用下面的方法可获取对应于太平洋时区的时区对象:  TimeZone tz=TimeZone.getTimeZone("PST");  调用方法getDefault()可以获取主机所处时区的对象。  TimeZone tz=TimeZone.getDefault();  (Ⅱ)调用以下方法可以获取时区的ID  ■public static synchronized String[] getavailableIDs(int rawOffset)  根据给定时区偏移值获取ID数组。同一时区的不同地区的ID可能不同,这是由于不同地区对是否实施夏时制意见不统一而造成的。  例String s[]=TimeZone.getAvailableIDs(-7*60*60*1000);  打印s,结果为s[0]=PNT,s[1]=MST  ■public static synchronized String[] getAvailableIDs()  获取提供的所有支持的ID。  ■public String getID()  获取特定时区对象的ID。  例 TimeZone tz=TimeZone.getDefault();  String s=tz.getID();  打印s,结果为s=CTT。  上面使用类的对象代表了一个特定的地理、政治或文化区域。Locale只是一种机制,它用来标识一类对象,Local本身并不包含此类对象。  要获取一个Locale的对象有两种方法:  (Ⅰ)调用Locale类的构造方法  Locale(String language,String country)  Locale(String language,String country,String variant)  参数说明:language??在ISO-639中定义的代码,由两个小写字母组成。       country??在ISO-3166中定义的代码,由两个大写字母组成。       variant??售货商以及特定浏览器的代码,例如使用WIN代表Windows。  (Ⅱ)调用Locale类中定义的常量  Local类提供了大量的常量供用户创建Locale对象。  例 Locale.CHINA    为中国创建一个Locale的对象。  类TimeZone和类Locale中的其它方法,读者可查阅API。  (5)public GregorianCalendar(int year,int month,int date)  (6)public GregorianCalendar(int year,int month,int date,int hour,int minute)  (7)public GregorianCalendar(int year,int month,int date,int hour,int minute,int second)  用给定的日期和时间创建一个GregorianCalendar的对象。  参数说明:  year-设定日历对象的变量YEAR;month-设定日历对象的变量MONTH;  date-设定日历对象的变量DATE;hour-设定日历对象的变量HOUR_OF_DAY;  minute-设定日历对象的变量MINUTE;second-设定日历对象的变量SECOND。  与Date类中不同的是year的值没有1900这个下限,而且year的值代表实际的年份。month的含义与Date类相同,0代表1月,11代表12月。  例 GregorianCalendar cal=new GregorianCalendar(1991,2,4)  cal的日期为1991年3月4号。  除了与Date中类似的方法外,Calendar类还提供了有关方法对日历进行滚动计算和数学计算。计算规则由给定的日历系统决定。进行日期计算时,有时会遇到信息不足或信息不实等特殊情况。Calendar采取了相应的方法解决这些问题。当信息不足时将采用缺省设置,在GregorianCalendar类中缺省设置一般为YEAR=1970,MONTH=JANUARY,DATE=1。  当信息不实时,Calendar将按下面的次序优先选择相应的Calendar的变量组合,并将其它有冲突的信息丢弃。  MONTH+DAY_OF_MONTH  MONTH+WEEK_OF_MONTH+DAY_OF_WEEK  MONTH+DAY_OF_WEEK_OF_MONTH+DAY_OF_WEEK  DAY_OF+YEAR  DAY_OF_WEEK_WEEK_OF_YEAR  HOUR_OF_DAY8.4 随机数类Random  Java实用工具类库中的类java.util.Random提供了产生各种类型随机数的方法。它可以产生int、long、float、double以及Goussian等类型的随机数。这也是它与java.lang.Math中的方法Random()最大的不同之处,后者只产生double型的随机数。  类Random中的方法十分简单,它只有两个构造方法和六个普通方法。  构造方法:  (1)public Random()  (2)public Random(long seed)  Java产生随机数需要有一个基值seed,在第一种方法中基值缺省,则将系统时间作为seed。  普通方法:  (1)public synonronized void setSeed(long seed)  该方法是设定基值seed。  (2)public int nextInt()  该方法是产生一个整型随机数。  (3)public long nextLong()  该方法是产生一个long型随机数。  (4)public float nextFloat()  该方法是产生一个Float型随机数。  (5)public double nextDouble()  该方法是产生一个Double型随机数。  (6)public synchronized double nextGoussian()  该方法是产生一个double型的Goussian随机数。  例8.2 RandomApp.java。  //import java.lang.*;  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   public static void main(String[] args){    Vector v1=new Vector();    Integer integer1=new Integer(1);    v1.addElement("one");    //加入的为字符串对象    v1.addElement(integer1);    v1.addElement(integer1);    //加入的为Integer的对象    v1.addElement("two");    v1.addElement(new Integer(2));    v1.addElement(integer1);    v1.addElement(integer1);    System.out.println("The vector v1 is:/n/t"+v1);    //将v1转换成字符串并打印    v1.insertElementAt("three",2);    v1.insertElementAt(new Float(3.9),3);    System.out.println("The vector v1(used method insertElementAt()) is:/n/t "+v1);    //往指定位置插入新的对象,指定位置后的对象依次往后顺延    v1.setElementAt("four",2);    System.out.println("The vector v1(used method setElementAt()) is:/n/t "+v1);    //将指定位置的对象设置为新的对象    v1.removeElement(integer1);    //从向量对象v1中删除对象integer1由于存在多个integer1所以从头开始    //找,删除找到的第一个integer1    Enumeration enum=v1.elements();    System.out.print("The vector v1(used method removeElement())is:");    while(enum.hasMoreElements())    System.out.print(enum.nextElement()+" ");    System.out.println();    //使用枚举类(Enumeration)的方法来获取向量对象的每个元素    System.out.println("The position of object 1(top-to-bottom):"     + v1.indexOf(integer1));    System.out.println("The position of object 1(tottom-to-top):"     +v1.lastIndexOf(integer1));    //按不同的方向查找对象integer1所处的位置    v1.setSize(4);    System.out.println("The new vector(resized the vector)is:"+v1);    //重新设置v1的大小,多余的元素被行弃   }  }  运行结果:  E:/java01>java VectorApp  The vector v1 is:     [one, 1, 1, two, 2, 1, 1]  The vector v1(used method insertElementAt()) is:     [one, 1, three, 3.9, 1, two, 2, 1, 1]  The vector v1(used method setElementAt()) is:     [one, 1, four, 3.9, 1, two, 2, 1, 1]  The vector v1(used method removeElement())is:one four 3.9 1 two 2 1 1  The position of object 1(top-to-bottom):3  The position of object 1(tottom-to-top):7  The new vector(resized the vector)is:[one, four, 3.9, 1]  E:/java01>  从例8.3运行的结果中可以清楚地了解上面各种方法的作用,另外还有几点需解释。  (1)类Vector定义了方法  public final int size()  此方法用于获取向量元素的个数。它的返回值是向是中实际存在的元素个数,而非向量容量。可以调用方法capactly()来获取容量值。  方法:  public final synchronized void setsize(int newsize)  此方法用来定义向量大小。若向量对象现有成员个数已超过了newsize的值,则超过部分的多余元素会丢失。  (2)程序中定义了Enumeration类的一个对象  Enumeration是java.util中的一个接口类,在Enumeration中封装了有关枚举数据集合的方法。  在Enumeration中提供了方法hawMoreElement()来判断集合中是束还有其它元素和方法nextElement()来获取下一个元素。利用这两个方法可以依次获得集合中元素。  Vector中提供方法:  public final synchronized Enumeration elements()  此方法将向量对象对应到一个枚举类型。java.util包中的其它类中也大都有这类方法,以便于用户获取对应的枚举类型。8.6 栈类Stack  Stack类是Vector类的子类。它向用户提供了堆栈这种高级的数据结构。栈的基本特性就是先进后出。即先放入栈中的元素将后被推出。Stack类中提供了相应方法完成栈的有关操作。  基本方法:  public Object push(Object Hem)  将Hem压入栈中,Hem可以是任何类的对象。  public Object pop()  弹出一个对象。  public Object peek()  返回栈顶元素,但不弹出此元素。  public int search(Object obj)  搜索对象obj,返回它所处的位置。  public boolean empty()  判别栈是否为空。  例8.4 StackApp.java使用了上面的各种方法。  例8.4 StackApp.java。  import java.lang.*;  import java.util.*;  public class StackApp{   public static void main(String args[]){    Stack sta=new Stack();    sta.push("Apple");    sta.push("banana");    sta.push("Cherry");    //压入的为字符串对象    sta.push(new Integer(2));    //压入的为Integer的对象,值为2    sta.push(new Float(3.5));    //压入的为Float的对象,值为3.5    System.out.println("The stack is,"+sta);    //对应栈sta    System.out.println("The top of stack is:"+sta.peek());    //对应栈顶元素,但不将此元素弹出    System.out.println("The position of object Cherry is:"    +sta.search("cherry"));    //打印对象Cherry所处的位置    System.out.print("Pop the element of the stack:");    while(!sta.empty())    System.out.print(sta.pop()+" ");    System.out.println();    //将栈中的元素依次弹出并打印。与第一次打印的sta的结果比较,可看出栈    //先进后出的特点   }  }  运行结果(略)8.7 哈希表类Hashtable  哈希表是一种重要的存储方式,也是一种常见的检索方法。其基本思想是将关系码的值作为自变量,通过一定的函数关系计算出对应的函数值,把这个数值解释为结点的存储地址,将结点存入计算得到存储地址所对应的存储单元。检索时采用检索关键码的方法。现在哈希表有一套完整的算法来进行插入、删除和解决冲突。在Java中哈希表用于存储对象,实现快速检索。  Java.util.Hashtable提供了种方法让用户使用哈希表,而不需要考虑其哈希表真正如何工作。  哈希表类中提供了三种构造方法,分别是:  public Hashtable()  public Hashtable(int initialcapacity)  public Hashtable(int initialCapacity,float loadFactor)  参数initialCapacity是Hashtable的初始容量,它的值应大于0。loadFactor又称装载因子,是一个0.0到0.1之间的float型的浮点数。它是一个百分比,表明了哈希表何时需要扩充,例如,有一哈希表,容量为100,而装载因子为0.9,那么当哈希表90%的容量已被使用时,此哈希表会自动扩充成一个更大的哈希表。如果用户不赋这些参数,系统会自动进行处理,而不需要用户操心。  Hashtable提供了基本的插入、检索等方法。  ■插入  public synchronized void put(Object key,Object value)给对象value设定一关键字key,并将其加到Hashtable中。若此关键字已经存在,则将此关键字对应的旧对象更新为新的对象Value。这表明在哈希表中相同的关键字不可能对应不同的对象(从哈希表的基本思想来看,这也是显而易见的)。  ■检索  public synchronized Object get(Object key)  根据给定关键字key获取相对应的对象。  public synchronized boolean containsKey(Object key)  判断哈希表中是否包含关键字key。  public synchronized boolean contains(Object value)  判断value是否是哈希表中的一个元素。  ■删除  public synchronized object remove(object key)  从哈希表中删除关键字key所对应的对象。  public synchronized void clear()  清除哈希表  另外,Hashtalbe还提供方法获取相对应的枚举集合:  public synchronized Enumeration keys()  返回关键字对应的枚举对象。  public synchronized Enumeration elements()  返回元素对应的枚举对象。  例8.5 Hashtable.java给出了使用Hashtable的例子。  例8.5 Hashtalbe.java。  //import java.lang.*;  import java.util.Hashtable;  import java.util.Enumeration;  public class HashApp{   public static void main(String args[]){    Hashtable hash=new Hashtable(2,(float)0.8);    //创建了一个哈希表的对象hash,初始容量为2,装载因子为0.8    hash.put("Jiangsu","Nanjing");    //将字符串对象"Jiangsu"给定一关键字"Nanjing",并将它加入hash    hash.put("Beijing","Beijing");    hash.put("Zhejiang","Hangzhou");    System.out.println("The hashtable hash1 is: "+hash);    System.out.println("The size of this hash table is "+hash.size());    //打印hash的内容和大小    Enumeration enum1=hash.elements();    System.out.print("The element of hash is: ");    while(enum1.hasMoreElements())     System.out.print(enum1.nextElement()+" ");    System.out.println();    //依次打印hash中的内容    if(hash.containsKey("Jiangsu"))     System.out.println("The capatial of Jiangsu is "+hash.get("Jiangsu"));    hash.remove("Beijing");    //删除关键字Beijing对应对象    System.out.println("The hashtable hash2 is: "+hash);    System.out.println("The size of this hash table is "+hash.size());   }  }  运行结果:  The hashtable hash1 is: {Beijing=Beijing, Zhejiang=Hangzhou, Jiangsu=Nanjing}  The size of this hash table is 3  The element of hash is: Beijing Hangzhou Nanjing  The capatial of Jiangsu is Nanjing  The hashtable hash2 is: {Zhejiang=Hangzhou, Jiangsu=Nanjing}  The size of this hash table is 2  Hashtable是Dictionary(字典)类的子类。在字典类中就把关键字对应到数据值。字典类是一个抽象类。在java.util中还有一个类Properties,它是Hashtable的子类。用它可以进行与对象属性相关的操作。8.8 位集合类BitSet  位集合类中封装了有关一组二进制数据的操作。  我们先来看一下例8.6 BitSetApp.java。  例8.6 BitSetApp.java  //import java.lang.*;  import java.util.BitSet;  public class BitSetApp{   private static int n=5;   public static void main(String[] args){    BitSet set1=new BitSet(n);    for(int i=0;i      Object obj = it.next(); // 得到下一个元素    }  由Collection接口派生的两个接口是List和Set。

List接口  List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。和下面要提到的Set不同,List允许有相同的元素。  除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。  实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

LinkedList类  LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。  注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:    List list = Collections.synchronizedList(new LinkedList(...));

ArrayList类  ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。  每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。  和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

Vector类  Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

Stack 类  Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

Set接口  Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。  很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。  请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

Map接口  请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Hashtable类  Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。  添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:    Hashtable numbers = new Hashtable();    numbers.put(“one”, new Integer(1));    numbers.put(“two”, new Integer(2));    numbers.put(“three”, new Integer(3));  要取出一个数,比如2,用相应的key:    Integer n = (Integer)numbers.get(“two”);    System.out.println(“two = ” + n);  由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。  如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。  Hashtable是同步的。

HashMap类  HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。

WeakHashMap类  WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

总结  如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。  如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。  要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。  尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有