首页 > 代码库 > java各类容器介绍

java各类容器介绍

     在编程中,我们几乎总需要组织一组同种类的对象,比如一群学生或者一群工人,由于他们数量的不可定,我们需要一个东西来帮助进行管理,这个用来管理的东西通常被称为容器。我们可以通过容器动态添加或删除对象,遍历全部或查找一个对象等等。java类库为我们提供了大量常用的容器构件。
     把对象放入容器的动作大同小异,把对象从容器中取出却各有不同,这正是每种容器的差异所在。容器类型大致可以分为以下两种:
Collection
     一个独立元素的序列,这些元素都服从一条或多条规则。List是使用限制最小的Collection了,它会按照插入的顺序保存元素,但你可以任意的访问所有元素。Queue按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序相同),而你只能取到排序在前面的元素。Stack按照先进后出的顺序进行排序,所以你只能取到最后进入容器的元素。而Set不能有重复元素。
     在我们使用的容器中,List似乎可以提供其他容器实现的相同功能,因为对象是你随意取的,既然如此,那又何必要有其他容器呢?事实上,对象的组织方式背后离不开各种数据结构,各个容器背后采用的数据结构是不同的,也就直接决定了你执行各种操作的效率,例如移动和取出元素。所以,选择一种容器就是选择它背后的数据结构,也就是选择了你进行某种操作的效率。
Map
     一组成对的"键值对"对象,允许你使用键来查找值。ArrayList允许你使用数字来查找值,因此在某种意义上讲,它将数字与对象关联在了一起。映射表允许我们使用另一个对象来查找某个对象,它也被称为"关联数组",因为它将某些对象与另外一些对象关联在一起;或者被称为"字典",因为你可以使用键对象来查找值对象,就像在字典中使用单词来定义一样。Map是强大的编程工具。

List

     有两种类型的List:
  • 基本的ArrayList:它长于随机访问元素(虽然使用较少),但是在List的中间插入和移除元素时较慢。这是由于它底层采用数组实现。
  • LinkedList:它在随机访问方面相对比较慢,但是能代价较低的在List中间进行插入和删除的元素。这种特性是由于底层采用了链表实现数据组织。

迭代器

Interator
     我们经常用到遍历容器对象的功能,用于访问、或者删除等,使用迭代器和多态可以在不使用容器真实类型的情况下遍历容器对象。
     迭代器是一个对象,它的工作是遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层的结构。此外,迭代器通常被称为轻量级对象:创建它的代价小。因此,经常可以见到对迭代器有些奇怪的限制;例如,Java的Iterator只能单向移动,这个Iterator只能用来:
  1. 使用方法iterator()要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素。
  2. 使用next()获得序列中的下一个元素。
  3. 使用hasNext()检查序列中是否还有元素。
  4. 使用remove()将迭代器新近返回的元素删除。
ListIterator
     ListIterator是一个更加强大的Iterator的子类型,它只能用于各种List类的访问。尽管Iterator只能向前移动,但是ListIterator可以双向移动。它还可以产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引,并且可以使用set()方法替换它访问过的最后一个元素。你可以通过调用listIterator()方法产生一个指向List开始处的ListInterator,并且还可以通过调用listInterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。

Stack

     "栈"通常是指"先进后出"的容器。有时栈也被称为叠加栈,因为最后"压入"栈的元素,第一个"弹出"栈。经常用来类比栈的事物是装有弹簧的储放器中的自助餐托盘,最后装入的托盘总是最先拿出使用的。
     由于List可以模拟Stack的行为,所以Stack类的里面实现使用了List。

Queue     

     队列是一个典型的先进先出(FIFO)的容器。即从容器的一端放入事物,从另一端取出,并且事物放入容器的顺序与取出的顺序是相同的。列队常被当作一种可靠的将对象从程序的某个区域传输到另一个区域的安全途径,队列在并发编程中特别重要,。
     LinkedList提供了方法以支持队列的行为,并且它实现了Queue接口,因此LinkedList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue。
PriorityQueue
     先进先出描述了最典型的队列规则。队列规则是指在给定一组队列中的元素的情况下,确定下一个弹出队列的元素的规则。先进先出声明的是下一个元素应该是等待时间最长的元素。
     优先级队列声明下一个弹出元素是最需要的元素(具有最高的优先级)。
     当你在PriorityQueue上调用offer()方法来插入一个元素时,这个对象会在队列中被排序。默认的排序将使用对象在队列中的自然顺序,但是你可以通过提供自己的Comparator来修改这个顺序。

Set

     Set不保存重复的元素(至于如何判断元素相同则较为复杂,稍后便会看到)。如果你试图将多个相同对象的多个实例添加到Set中,那么它就会阻止这种重复现象。Set中最常被使用的是测试归属性,你可以很容易地询问某个对象是否在某个Set中。正因如此,查找就成为了Set中最重要的操作,因此你通常都会选择一个HashSet的实现,它专门对快速查找进行了优化。
     Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只是行为不同。
     如果使用的是HashSet而对Set进行输出的话,会发现输出结果无规律可循,这是由于HashSet使用了散列。TreeSet将元素储存在红-黑树数据结构中,所以输出会有顺序。LinkedHashSet因为查询速度的原因也使用了散列,但是看起来它使用了链表来维护元素的插入顺序。
     使用TreeSet时对象必须支持可比较(Comparable),在TreeMap中也有所体现。
     HashSet依靠hashcode(),equals()完成重复元素的判断,在HashMap中也有所体现。

Map

     Map提供对键值对的访问,在实现上与Set近似,同样提供HashMap,TreeMap,LinkedHashMap使用。一般如果不排序输出,则使用HashMap。

Foreach与迭代器

     下面展示Foreach应用在容器上。
public class ForEachCollections {
     public static void main(String[] args) {
          Collection<String> cs = new LinkedList<String>();
          Collection.addAll(cs,"Take the long way home".split(" "));
          for(String s : cs)
               System.out.print("‘" + s + "‘")
     }
}
     由于cs是一个collection,所以这段代码展示了能够与foreach一起工作是所有Collection对象的特性。
     之所以能够工作,是因为Java引入了新的被称为Iterator的接口,该接口包含一个能够产生Iterator的iterator()方法,并且Iterator接口被foreach用来在序列中移动。因此,如果你创建了任何实现Iterator的类,都可以将它用于foreach语句中。
     实际上,foreach语句提供的功能是迭代器功能的子集,迭代器除了能获取该引用,还能删除该引用,而foreach只能获取该引用。


java各类容器介绍