编程那点事编程那点事

专注编程入门及提高
探究程序员职业规划之道!

对象导论:容器(集合)

通常说来,如果不知道在解决某个特定问题时需要多少个对象,或者它们将存活多久,那么就不可能知道如何存储这些对象。如何才能知道需要多少空间来创建这些对象呢?答案是你不可能知道,因为这类信息只有在运行时才能获得。

对于面向对象设计中的大多数问题而言,这个问题的解决方案似乎过于轻率:创建另一种对象类型。这种新的对象类型持有对其他对象的引用。当然,你可以用在大多数言语中都有的数组类型来实现相同的功能。但是这个通常被称为容器(即集合)的新对象,在任何需要时都可以扩充自己以容纳你置于其中的所有东西。因此不需要知道将来会把多少个对象置于容器中,只需要创建一个容器对象,然后让他处理所有的细节。

幸运的是,好的OOP语言都有一组容器,他们作为开发包的一部分。在C++中,容器是标准C++类库的一部分,经常被称为标准模板类库。在某些类库中,一两个通用容器足够满足所有的需要;但是在其他类库中,具有满足不同需要的各种类型的容器,例如List(用于存储序列),Map(也被称为关联数组,用来建立对象之间的关联),Set(每种对象类型只持有一个),以及诸如队列、树、堆栈等更多的构件。

从设计的观点来看,真正需要的只是一个可以被操作,从而解决问题的序列。如果单一类型的容器可以满足所有需要,那么就没有理由设计不同种类的序列了。然而还是需要对容器有所选择,这有两个原因。

第一,不同容器提供了不同类型的接口和外部行为。堆栈相比于队列就具备不同的接口和行为。它们之中的某种容器提供的解决方案可能比其他容器要灵活的多。

第二,不同的容器对于某些操作具有不同的效率。

最好的例子就是两种List的比较:ArrayList和LinkedList。它们都是具有相同接口和外部行为的简单的序列,但是他们对某些操作所花费的代价却有天壤之别。在ArrayList中,随机访问元素是一个花费固定时间的操作;但是,对LinkedList来说,随机选取元素需要在列表中移动,这种代价是高昂的,访问越靠近表尾的元素, 花费的时间越长,另一方面,如果想在序列中插入一个元素,LinkedList的开销却比ArrayList要小。

上述操作以及其他操作的效率,依序列底层结构的不同而存在很大的差异。我们可以在一开始使用LinkedList构建程序,而在优化系统时改用ArrayList。接口List所带来的抽象,把在容器之间进行转换时对代码产生的影响降到最小限度。

未经允许不得转载: 技术文章 » Java编程 » 对象导论:容器(集合)