- 论坛徽章:
- 0
|
三、Java2中的容器类库自Java1.2之后Java版本统称为Java2,Java2中的容器类库才可以说是一种真正意义上的集合框架的实现。基本完全重新设计,但是又对Java1中的一些容器类库在新的设计上进行了保留,这主要是为了向下兼容的目的,当用Java2开发程序时,应尽量避免使用它们,Java2的集合框架已经完全可以满足你的需求。有一点需要提醒的是,在Java1中容器类库是同步化的,而Java2中的容器类库都是非同步化,这可能是对执行效率进行考虑的结果。
Java2中的集合框架提供了一套设计优良的接口和类,使程序员操作成批的数据或对象元素极为方便。这些接口和类有很多对抽象数据类型操作的API,而这是我们常用的且在数据结构中熟知的。例如Maps,Sets,Lists,Arrays等。并且Java用面向对象的设计对这些数据结构和算法进行了封装,这就极大的减化了程序员编程时的负担。程序员也可以以这个集合框架为基础,定义更高级别的数据抽象,比如栈、队列和线程安全的集合等,从而满足自己的需要。
Java2的集合框架,抽其核心,主要有三类:List、Set和Map。如下图所示:
![]()
从图上可以看出,List和Set继承了Collection,而Map则独成一体。初看上去可能会对Map独成一体感到不解,它为什么不也继承Collection呢?但是仔细想想,这种设计是合理的。一个Map提供了通过Key对Map中存储的Value进行访问,也就是说它操作的都是成对的对象元素,比如put()和get()方法,而这是一个Set或List所不就具备的。当然在需要时,你可以由keySet()方法或values()方法从一个Map中得到键的Set集或值的Collection集。
1、Collection接口提供了一组操作成批对象的方法,用UML表示的方法列表如下:
它提供了基本操作如添加、删除。它也支持查询操作如是否为空isEmpty()方法等。为了支持对Collection进行独立操作,Java的集合框架给出了一个Iterator,它使得你可以泛型操作一个Collection,而不需知道这个Collection的具体实现类型是什么。它的功能与Java1中的Enumeration类似,只是更易掌握和使用,功能也更强大。在建立集合框架时,Sun的开发团队考虑到需要提供一些灵活的接口,用来操作成批的元素,又为了设计的简便,就把那些对集合进行可选操作的方法与基本方法放到了一起。因为一个接口的实现者必须提供对接口中定义的所有方法的实现,这就需要一种途径让调用者知道它正在调用 的可选方法当前不支持。最后开发团队选择使用一种信号,也即抛出一种不支持操作例外(UnsupportedOperationException),如果你在使用一个Collection中遇到一个上述的例外,那就意味着你的操作失败,比如你对一个只读Collection添加一个元素时,你就会得到一个不支持操作例外。在你实现一个集合接口时,你可以很容易的在你不想让用户使用的方法中抛出UnsupportOperationException来告诉使用者这个方法当前没有实现,UnsupportOperationException是RuntimeException的一个扩展。
另外Java2的容器类库还有一种Fail fast的机制。比如你正在用一个Iterator遍历一个容器中的对象,这时另外一个线程或进程对那个容器进行了修改,那么再用next()方法时可能会有灾难性的后果,而这是你不愿看到的,这时就会引发一个ConcurrentModificationException例外。这就是fail-fast。
2、List接口对Collection进行了简单的扩充,它的具体实现类常用的有ArrayList和LinkedList。你可以将任何东西放到一个List容器中,并在需要时从中取出。ArrayList从其命名中可以看出它是一种类似数组的形式进行存储,因此它的随机访问速度极快,而LinkedList的内部实现是链表,它适合于在链表中间需要频繁进行插入和删除操作。在具体应用时可以根据需要自由选择。前面说的Iterator只能对容器进行向前遍历,而ListIterator则继承了Iterator的思想,并提供了对List进行双向遍历的方法。
3、Set接口也是Collection的一种扩展,而与List不同的时,在Set中的对象元素不能重复,也就是说你不能把同样的东西两次放入同一个Set容器中。它的常用具体实现有HashSet和TreeSet类。HashSet能快速定位一个元素,但是你放到HashSet中的对象需要实现hashCode()方法,它使用了前面说过的哈希码的算法。而TreeSet则将放入其中的元素按序存放,这就要求你放入其中的对象是可排序的,这就用到了集合框架提供的另外两个实用类Comparable和Comparator。一个类是可排序的,它就应该实现Comparable接口。有时多个类具有相同的排序算法,那就不需要在每分别重复定义相同的排序算法,只要实现Comparator接口即可。
集合框架中还有两个很实用的公用类:Collections和Arrays。Collections提供了对一个Collection容器进行诸如排序、复制、查找和填充等一些非常有用的方法,Arrays则是对一个数组进行类似的操作。
4、Map是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求。你可以将任意多个键都映射到一个值对象上,这不会发生任何问题(不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象)。Map有两种比较常用的实现:HashMap和TreeMap。HashMap也用到了哈希码的算法,以便快速查找一个键,TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。键和值的关联很简单,用pub(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。
四、未来的Java容器类库前面几部分对Java中容器类库的过去与现在的状况进行了讨论,然而就在写下此文时,Sun已经开始通过某种途径分发J2SE1.5的Alpha测试版了。在今年的JavaOne大会上,诸多大师描绘了Java的美好未来与在下一个版本中即将加入的一些新特性,其中为容器类库加入的一个重要特性就是泛型。
其实泛型并不是什么新东西,在其它一些面向对象的语言中早已存在,如C++。泛型的基本目标很简单:能够保证你使用一种类型安全的容器。那么到底怎样一种类型安全呢?我们先看下面这一段没有使用泛型特性的代码:
import java.util.*;
public class Generics{
/**
* 输出一个String类型的列表,假设所给参数list中所有元素都为String。
*/
public static void printList(
List
list){
for(int i=0;i上面的代码很简单,定义了一个静态方法来打印一个元素为String类型的List,然而正如你看到的一样,如果你试着将(1)行中前面的注释去掉,你就会得到一个ClassCastException例外,因为printList会将list中的每个元素都转型为String,而在遇到最后一个元素时发现它是一个Generics类型从而无法完成转型,例外就被抛出。这种情况在Java编程中很容易出现,原因是Java的容器类库通常保存的是Object类型,而这是所有类的直接或间接超类,这就允许你将任何类型的元素添加到一个List中而不会给你任何提示,有经验的程序员可能会自己编写一个容器类来限制添加到其中的元素,这是一个编程技巧。但是现在我们就再也不用那样做了,泛型机制会为我们做好这件事。那就看一下用泛型机制对上面代码进行的改进:
import java.util.*;
public class Generics{
/**
* 输出一个String类型的列表,限制了所给参数list中所有元素都为String
*/
public static void printList(
ArrayList
list){
for(int i=0;i(); //注意此行中声明语法的变化
for(int i=0;i
正如在代码中所看到的,容器的声明有了变化,即在一个容器类后面用来说明你想要放入这个容器中的元素类型,那么接下来你只能向这个容器加那种类型,否则编译就无法通过。在printList中也省去了转型的麻烦。当然有了泛型,并不是说以前的声明方法不能用了,你完全可以还用以前的方法,这没有任何问题。其实根据JSR中对for语句功能的增强,遍历一个容器也会更加简单。
当然泛型的使用方法不只如此,这里并没有对它进行完整描述,只想告诉你,泛型确实为我们编程提供了便利,但是仍然需要用心去学习和掌握。
随着Java的进一步完善,它的功能和易用性也得到提高,我有理由相信Java在计算机语言中所占的位置也会更加牢固,让喜爱Java的人更加喜爱它。祝愿Java一路走好!
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/11995/showart_154584.html |
|