通 常希望循环通过类集中的元素。例如,可能会希望显示每一个元素。到目前为止,处 理这个问题的最简单方法是使用 iterator,iterator 是一个或者实现 Iterator 或者实现 ListIterator 接口的对象。Iterator 可以完成循环通过类集,从而获得或删除元素。ListIterator 扩展 Iterator,允许双向遍历列表,并可以修改单元
在通过迭代函数访问类集之前,必须得到一个迭代函数。每一个 Collection 类都提供一 个 iterator()函数,该函数返回一个对类集头的迭代函数。通过使用这个迭代函数对象,可以
访问类集中的每一个元素,一次一个元素。通常,使用迭代函数循环通过类集的内容,步骤 如下:
–1. 通过调用类集的 iterator( )方法获得对类集头的迭代函数。
–2. 建立一个调用 hasNext( )方法的循环,只要 hasNext( )返回 true,就进行循环迭代。
–3. 在循环内部,通过调用 next( )方法来得到每一个元素。
对于执行 List 的类集,也可以通过调用 ListIterator 来获得迭代函数。正如上面解释的那 样,列表迭代函数提供了前向或后向访问类集的能力,并可让你修改元素。否则,ListIterator 如同 Iterator 功能一样。
Iterator 和 ListIterator。它使用 ArrayList 对象,但是总的原则适用于任何类型的类集。 当然,ListIterator 只适用于那些实现 List 接口的类集。
为了简单,前面的例子在类集中存储内置的对象,如 String 或 Integer。当然,类集并没 有被限制为只能存储内置的对象。完全相反的是,类集的能力是它能存储任何类型的对象,包括你所创建的类的对象。
除 了类集,Java 2 还在 java.util 中增加了映射。映射(map)是一个存储关键字和值的 关联或者说是关键字/值对的对象。给定一个关键字,可以得到它的值。关键字和值都是对 象。关键字必须是唯一的。但值是可以重复的。有些映射可以接收 null 关键字和 null 值。而 有的则不行。
Map 接口映射唯一关键字到值。关键字(key)是以后用于检索值的对象。给定一个关 键字和一个值,可以存储这个值到一个 Map 对象中。当这个值被存储以后,就可以使用它 的关键字来检索它。当调用的映射中没有项存在时,其中的几种方法会引发一个 NoSuchElementException 异常。而当对象与映射中的元素不兼容时,引发一个 ClassCastException 异常。如果试图使用映射不允许使用的 null 对象时,则引发一个 NullPointerException 异常。当试图改变一个不允许修改的映射时,则引发一个
UnsupportedOperationExce
映射循环使用两个基本操作:get()和 put()。使用 put()方法可以将一个指定了关键字和 值的值加入映射。为了得到值,可以通过将关键字作为参数来调用 get()方法。调用返回该值。
映 射不是类集,但可以获得映射的类集“视图”。为了实现这种功能,可以使用 entrySet() 方法,它返回一个包含了映射中元素的集合(Set)。为了得到关键字的类集“视图”,可以 使用 keySet()方法。为了得到值的类集“视图”,可以使用 values()方法。类集“视图”是将映射 集成到类集框架内的手段。
SortedMap 接口扩展了 Map,它确保了各项按关键字升序排序。当调用映射中没有的项 时,其中的几种方法引发一个 NoSuchElementException 异常。当对象与映射中的元素不兼容 时,则引发一个 ClassCastException 异常。当试图使用映射不允许使用的 null 对象时,则引 发一个 NullPointerException 异常。
排序映射允许对子映射(换句话说,就是映射的子集)进行高效的处理。使用 headMap(),
tailMap()或 subMap()方法可以获得子映射。调用 firstKey()方法可以获得集合的第一个关键字。 而调用 lastKey()方法可以获得集合的最后一个关键字。
16.Map.Entry
Map.Entry 接口使得可以操作映射的输入。回想由 Map 接口说明的 entrySet()方法,调 用该方法返回一个包含映射输入的集合(Set)。这些集合元素的每一个都是一个 Map.Entry 对象。
17.HashMap
HashMap 类使用散列表实现 Map 接口。这允许一些基本操作如 get()和 put()的运行时间 保持恒定,即便对大型集合,也是这样的。
•下面的构造函数定义为:
–HashMap( )
–HashMap(Map m)
–HashMap(int capacity)
–HashMap(int capacity, float fillRatio)
•第一种形式构造一个默认的散列映射。
•第二种形式用 m 的元素初始化散列映射。
•第三种形式将散列映射的容量初始化为 capacity。
•第四种形式用它的参数同时初始化散列映射的容量和填充比。容量和填充比的含义与前面 介绍的 HashSet 中的容量和填充比相同。
HashMap 实现 Map 并扩展 AbstractMap。它本身并没有增加任何新的方法。应该注意的 是散列映射并不保证它的元素的顺序。因此,元素加入散列映射的顺序并不一定是它们被迭 代函数读出的顺序。映射的内容通过使用由调用函数 entrySet()而获得的集合“视图”而显示出来。关键字和值通过调用由 Map.Entry 定义的 getKey()和 getValue()方法而显示。。put()方法自动用新值替换与指定关键字相关联的原先的值。
18.TreeMap
•下面的 TreeMap 构造函数定义为:
–TreeMap( )
–TreeMap(Comparator comp)
–TreeMap(Map m)
–TreeMap(SortedMap sm)
•第一种形式构造一个空树的映射,该映射使用其关键字的自然顺序来排序。
•第二种形式构造一个空的基于树的映射,该映射通过使用 Comparator comp 来排序(比较 函数 Comparators 将在后面进行讨论)。
•第三种形式用从 m 的输入初始化树映射,该映射使用关键字的自然顺序来排序。
•第四种形式用从 sm 的输入来初始化一个树映射,该映射将按与 sm 相同的顺序来排序
TreeMap 实现 SortedMap 并且扩展 AbstractMap。而它本身并没有另外定义其他方法。
TreeSet 和 TreeMap 都按排序顺序存储元素。然而,精确定义采用何种“排序顺序”的是 比较函数。通常在默认的情况下,这些类通过使用被 Java 称之为“自然顺序”的顺序存储它 们的元素,而这种顺序通常也是你所需要的(A 在 B 的前面,1 在 2 的前面,等等)。如果需要用不同的方法对元素进行排序,可以在构造集合或映射时,指定一个 Comparator 对象。 这样做为你提供了一种精确控制如何将元素储存到排序类集和映射中的能力。
Comparator 接口定义了两个方法:compare( )和 equals( )。这里给出的 compare( )方法按 顺序比较了两个元素:int compare(Object obj1, Object obj2),obj1 和 obj2 是被比较的两个对 象。当两个对象相等时,该方法返回 0;当 obj1 大于 obj2 时,返回一个正值;否则,返回一个负值。如果用于比较的对象的类型不兼容的话,该方法引发一个 ClassCastException 异 常。通过覆盖 compare(),可以改变对象排序的方式。例如,通过创建一个颠倒比较输出的比较函数,可以实现按逆向排序。这里给出的 equals( )方法,测试一个对象是否与调用比较函 数相等:boolean equals(Object obj),obj 是被用来进行相等测试的对象。如果 obj 和调用 对象都是 Comparator 的对象并且使用相同的排序。该方法返回 true。否则返回 false。重写 equals( )方法是没有必要的,大多数简单的比较函数都不这样做。
20.类集算法
类集 框架定义了几种能用于类集和映射的算法。在 Collections 类中,这些算法被定义为 静态方法。当试图比较不兼容的类型时,其中的一些算法引发一个 ClassCastException 异常; 而当试图改变一个不可改变的类集时,则引发一个 UnsupportedOperationExce
Java 2 在 java.util 中新增加了一个叫做 Arrays 的类。这个类提供了各种在进行数组运算 时很有用的方法。尽管这些方法在技术上不属于类集框架,但它们提供了跨越类集和数组的 桥梁。在这一节中,分析由 Arrays 定义的每一种方法。asList()方法返回一个被指定数组支持 的 List。换句话说,列表和数组访问的是同一个单元。它具有如下的形式:
–static List asList(Object[ ] array)
–这里 array 是包含了数据的数组
binarySearch()方法使用二分法搜索寻找指定的值。该方法必须应用于排序数组。它具有 如下的形式:
–static intbinarySearch(byte[ ] array, byte value)
–static intbinarySearch(char[ ] array, char value)
–static intbinarySearch(double[ ] array, double value)
–static intbinarySearch(float[ ] array, float value)
–static intbinarySearch(int[ ] array, intvalue)
–static intbinarySearch(long[ ] array, long value)
–static intbinarySearch(short[ ] array, short value)
–static intbinarySearch(Object[ ] array, Object value)
–static intbinarySearch(Object[ ] array, Object value, Comparator c)
这 里,array 是被搜索的数组,而 value 是被查找的值。当 array 中包含的元素是不可比 较的(例如 Double 和 StringBuffer)或者当 value 与 array 中的类型不兼容时,后两种形式引 发一个 ClassCastException 异常。在最后一种形式中,比较函数(Comparator)c 用于确定 array 中的元素的顺序。在所有的形式中,如果 array 中含有 value,则返回该元素的下标。否则, 返回一个负值。
22.以前版本遗留下来的类和接口
22.1.Enumeration
Enumeration 接口定义了可以对一个对象的类集中的元素进行枚举(一次获得一个)的 方法。这个接口尽管没有被摈弃,但已经被 Iterator 所替代。Enumeration 对新程序来说是 过时的。然而它仍被几种从以前版本遗留下来的类(例如 Vector 和 Properties)所定义的方 法使用,被几种其他的 API 类所使用以及被目前广泛使用的应用程序所使用。
•Enumeration 指定下面的两个方法:
–boolean hasMoreElements( )
–Object nextElement( )
–执行后,当仍有更多的元素可提取时,hasMoreElements()方法一定返回 true。当所有元素 都被枚举了,则返回 false。nextElement()方法将枚举中的下一个对象做为一个类属 Object的引用而返回。也就是每次调用 nextElement()方法获得枚举中的下一个对象。调用例程必须将那个对象转换为包含在枚举内的对象类型
22.2.Vector
Vector 实现动态数组。这与 ArrayList 相似,但两者不同的是:Vector 是同步的,并且它 包含了许多不属于类集框架的从以前版本遗留下来的方法。随着 Java 2 的公布,Vector 被重 新设计来扩展 AbstractList 和实现 List 接口,因此现在它与类集是完全兼容的
•这里是 Vector 的构造函数:
–Vector( )
–Vector(int size)
–Vector(int size, int incr)
–Vector(Collection c)
•第一种形式创建一个原始大小为 10 的默认矢量。
•第二种形式创建一个其原始容量由 size 指定的矢量。
•第三种形式创建一个其原始容量由 size 指定,并且它的增量由 incr 指定的矢量。增量指定 了矢量每次允许向上改变大小的元素的个数。
•第四种形式创建一个包含了类集 c 中元素的矢量。这个构造函数是在 Java 2 中新增加的。
所有的矢量开始都有一个原始的容量。在这个原始容量达到以后,下一次再试图向矢量 中存储对象时,矢量自动为那个对象分配空间同时为别的对象增加额外的空间。通过分配超过需要的内存,矢量减小了可能产生的分配的次数。这种次数的减少是很重要的,因为分配 内存是很花时间的。在每次再分配中,分配的额外空间的总数由在创建矢量时指定的增量来 确定。如果没有指定增量,在每个分配周期,矢量的大小增一倍。
•Vector 定义了下面的保护数据成员:
–int capacityIncrement;
–int elementCount;
–Object elementData[ ];
–增量值被存储在 capacityIncrement 中。矢量中的当前元素的个数被存储在 elementCount中。保存矢量的数组被存储在 elementData 中。因 为 Vector 实现 List,所以可以像使用 ArrayList 的一个实例那样使用矢量。也可以使用 它的从以前版本遗留下来的方法来操作它。例如,在后面实例化 Vector,可以通过调用 addElement()方法而为其增加一个元素。调用 elementAt()方法可以获得指定位置处的元素。 调用 firstElement()方法可以得到矢量的第一个元素。调用 lastElement()方法可以检索到矢量 的最后一个元素。使用 indexOf()和 lastIndexOf()方法可以获得元素的下标。调用 removeElement()或 removeElementAt()方法可以删除元素。随着 Java 2 的公布,Vector 增加了对迭代函数的支持。现在可以使用迭代函数来替代枚 举去遍历对象。例如,下面的基于迭代函数的程序代码:
// use an iterator to display contentsIterator vItr = v.iterator();System.out.println(” \nElements in vector:”);while(vItr.hasNext()) System.out.print(vItr.next() + ” “);System.out.println();因为建议不要使编写枚举新的程序代码,所以通常可以使用迭代函数来对矢量的内容进行枚举。当然,业已存在的大量的老程序采用了枚举。不过幸运的是,枚举和迭代函数的工 作方式几乎相同。
22.3.Stack
Stack 是 Vector 的一个子类,它实现标准的后进先出堆栈。Stack 仅仅定义了创建空堆栈 的默认构造函数。Stack 包括了由 Vector 定义的所有方法,同时增加了几种它自己定义的方 法。
22.4.Dictionary
字典(Dictionary)是一个表示关键字/值存储库的抽象类,同时它的操作也很像映射(Map)。给定一个关键字和值,可以将值存储到字典(Dictionary)对象中。一旦这个值被 存储了,就能够用它的关键字来检索它。因此,与映射一样,字典可以被当做关键字/值对列表来考虑。尽管在 Java 2 中并没有摈弃字典(Dictionary),由于它被映射(Map)所取代, 从而被认为是过时的。然而由于目前 Dictionary 被广泛地使用,因此这里仍对它进行详细的讨论。
散 列表(Hashtable)是原始 java.util 中的一部分同时也是 Dictionary 的一个具体实现。 然而,Java2 重新设计了散列表(Hashtable)以便它也能实现映射(Map)接口。因此现在 Hashtable 也被集成到类集框架中。它与 HashMap 相似,但它是同步的。和 HashMap 一样, Hashtable 将关键字/值对存储到散列表中。使用 Hashtable 时,指定一个对象作为关键字,同时指定与该关键字相关联的值。接着该关键字被散列,而把得到的散列值作为存储在表中 的值的下标。散 列表仅仅可以存储重载由 Object 定义的 hashCode()和 equals()方法的对象。hashCode() 方法计算和返回对象的散列码。当然,equals()方法比较两个对象。幸运的是,许多 Java 内 置的类已经实现了 hashCode()方法。例如,大多数常见的 Hashtable 类型使用字符串(String)对象作为关键字。String 实现 hashCode()和 equals()方法。
•Hashtable 的构造函数如下所示:
–Hashtable( )
–Hashtable(int size)
–Hashtable(int size, float fillRatio)
–Hashtable(Map m)
•第一种形式是默认的构造函数。
•第二种形式创建一个散列表,该散列表具有由 size 指定的原始大小。
• 第三种形式创建一个散列表,该散列表具有由 size 指定的原始大小和由 fillRatio 指定的填 充比。填充比必须介于 0.0 和 1.0 之间,它决定了在散列表向上调整大小之前散列表的充满 度。具体地说,当元素的个数大于散列表的容量乘以它的填充比时,散列表被扩展。如果没有指定填充比,默认使用 0.75。最后,
•第四种形式创建一个散列表,该散列表用 m 中的元素初始化。散列表的容量被设为 m 中 元素的个数的两倍。默认的填充因子设为 0.75。第四种构造函数是在 Java 2 中新增加的。
重 要的一点是:和映射类一样,Hashtable 不直接支持迭代函数。因此,上面的程序使 用枚举来显示 balance 的内容。然而,我们可以获得允许使用迭代函数的散列表的集合视图。 为了实现它,可以简单地使用由 Map 定义的一个类集“视图”方法,如 entrySet()或 keySet() 方法。例如,可以获得关键字的一个集合“视图”,并遍历这些关键字。
22.6.Properties
属 性(Properties)是 Hashtable 的一个子类。它用来保持值的列表,在其中关键字和值 都是字符串(String)。Properties 类被许多其他的 Java 类所使用。例如,当获得系统环境 值时,System.getProperties()返回对象的类型。Properties 类的一个有用的功能是可以指定一个默认属性,如果没有值与特定的关键字 相关联,则返回这个默认属性。例如,默认值可以与关键字一起在 getProperty()方法中被指定——如 getProperty(“name”,“default value”)。如果“name”值没有找到,则返回“default value”。当构造一个 Properties 对象时,可以传递 Properties 的另一个实例做为新实例的默认值。在这 种情况下,如果对一个给定的 Properties 对象调用 getProperty(“foo”),而“foo”并不存在时, Java 在默认 Properties 对象中寻找“foo”。它允许默认属性的任意层嵌套。Properties 的一个 最有用的方面是可以利用 store()和 load()方法方便地对包含在属性(Properties)对象中的信 息进行存储或从盘中装入信息。在任何时候,都可以将一个属性(Properties)对象写入流 或从中将其读出。这使得属性列表特别方便实现简单的数据库。
类集总结
原文转载黄SIR的博客:http://www.hcfeel.com/archives/62