Map、Set、Iterator迭代详解与Java平台的集合框架

Map、Set、Iterator迭代详解

Map接口定义了四种类型的方法,每个Map都包含这些方法。

equals(Object o)比较指定对象与此Map的等价性。
hashCode()返回此Map的哈希码。

Map定义了几个用于插放和删除元素的变换方法。
remove(Object key) 从Map中删除键和关联的值。
put(object key,Object value) 将指定值与指定键相关联。
clear() 从Map虽删除所有映射。
putAll(Map t) 将指定Map中的所有映射复制到此Map。

查看Map
迭代Map中的元素不存在直接了当的方法。假如要查询某个Map以了解其哪些元素满足特定查询或假如要迭代其所有元素,则您首先需要获取该

Map的“视图”。有三种可能的视图:所有键值对、所有键、所有值。前两个视图均返回Set对象,第三个视图返回Collection对象。就这两种

情况而言,问题到这里并没有结束,这是因为您无法直接迭代Collection对象或Set对象。要进行迭代,您必须获得一个Iterator对象。因此要

迭代Map的元素,必须进行如下编码:
Iterator keyValuePairs = aMap.entrySet().iterator();
Iterator keys=aMap.keySet().iterator();
Iterator values=aMap.values().iterator();
值得注意的是,这些对象实际上是基础Map的视图,而不是包含所有元素的副本。

使用Iterator对象,您可以遍历Map的元素,还可以删除Map中的元素。
EnterySet()返回Map中所包含映射的Set视图。Set中的每个元素都是一个Map.Entry对象,可以使用getKey()和getValue()方法访问后者的键元

素和值元素。
keySet()返回Map中所包含键的Set视图。删除Set中的元素还将删除Map中相应原映射。
values()返回Map中所包含值的Collection视图。删除Collection中的元素还将删除Map中相应的映射

Map访问和测试方法:
get(Object key) 返回与指定键关联的值
containsKey(Object key) 假如Map包含指定键的映射,则返回True
isEmpty() 假如Map不包含键-值映射,则返回True
size() 返回Map中的键值映射的数目。

Set(interface):存入Set的每个元素必须是唯一的,因为Set不保存重复元素。加入Set的Object必须定义equals()方法以确保对象的唯一性。

Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开人员不需要了解该序列的底层结构。迭代器通常被称为“轻量

级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时

,它返回序列的第一个元素。使用next()获得序列中的下一个元素。使用hasNext()检查序列中是否还有元素。使用remove()将迭代器新返回的元素删除。

 

 


Java平台的集合框架

“集合框架”主要由一组用来操作对象的接口组成。不同接口描述一组不同数据类型。
集合接口:6个接口,表示不同集合类型,是集合框架的基础。
抽象类:5个抽象类,对集合接口的部分实现。可扩展为自定义集合类。
实现类:8个实现类,对接口的具体实现。
在很大程度上,一旦您理解了接口,您就理解了框架。虽然您总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上;

因此,允许您更基本的数据结构而不必改变其它代码。
Collection接口是一组允许重复的对象。
Set接口继承Collection,但不允许重复,使用自己内部的排列机制。
List接口继承Collection,允许重复,以元素安插的次序来放置元素,不会重新排列。
Map接口是一组成对的键-值对象。Map中不能有重复的Key.拥有自己的内部排列机制。


容器中的元素类型都为Object。从容器取得元素时,必须把它转换成原来的类型。


集合接口:
Collection接口:用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。
1、单元素添加、删除操作:
Boolean add(Object o):将对象添加到集合
Boolean remove (Object o):如果集体中有与O相匹配的对象,则删除对象O。

2、查询操作:
Int size():返回当前集合中元素的数量
Boolean isEmpty():判断集合中是否有任何元素。
Boolean contains(Object o):查找集合中是否否有对象O
Iterator iterator():返回一个迭代器,用来访问集合中的各个元素。
3、组操作:作用于元素组或整个集合
Boolean containsAll(Collection c):查找集合中是否含有集合C中所有元素
Boolean addAll(Collection c):将集合C中所有元素添加到该集合。
Void clear():删除集合中所有元素。
Void removeAll(Collection c):从集合中删除集合C中的所有元素。
Void retainAll(Collection c):从集合中删除集合C中不包含的元素
4、Collection转换为Object数组:
Object[] toArray():返回一个内含集合所有元素的Array
Object[] toArray(Object[] a):返回一个内含集合所有元素的Array.运行期返回的Array和参数A的型别相同,需要转换为正确型别。
此外,您还可以把集合转换成其它任何其它的对象数组。但是,您不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。
Collection不提供get()方法。如果要遍历Collection中的元素,就必须用Iterator.

AbstractCollection抽象类
AbstactCollection类提供具体“集合框架”类的基本功能。虽然您可以自实现Collection接口的所有方法,但是,除了Iterator()和Size()方

法在恰当的子类中实现以外,其它所有方法都由AbstractCollection类来提供实现。如果子类不覆盖某些方法,可选的方法将抛出异常。

Iterator接口
Collection接口的Iterator()方法返回一个Iterator。Iterator接口方法能以迭代方式逐个访问集合中各个元素,并安全的从Collection中除

去适当的元素。
1、Boolean hasNext():判断是否存在另一个可访问的元素。
2、Object next():返回要访问的下一个元素。如果到达集合结尾,则抛出NoSuchElementException异常。
3、Void remove():删除上次访问返回的对象。本方法必须紧跟在一个元素的访问后执行。如果上次访问后集合已被修改,方法将抛出

IIIegalStateException。
Iterator中删除操作对底层Collection也有影响。
迭代器是故障快速修复的。这意味着,当另一个线程修改底层集合的时候,如果您正在用Iterator遍历集合,那么,Iterator就会抛出

ConcurrentModificationException异常并立刻失败。


List接口继承了Collection接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。
1、面向位置的操作包括插入某个元素,还包括获取、除去或更改元素的功能。在List中搜索元素可以从列表的头部或尾部开始,如果找到元素

,还将报告元素所在的位置:
Void add(int index,Object element):在指定位置Index上添加元素element
Boolean addAll(int index,Collection c):将集合C的所有元素添加到指定位置Index
Object get(int index):返回List中指定位置的元素
Int indexOf(Object o):返回第一个出现元素O的位置,否则返回-1
Int lastIndexOf(Object o):返回最后一个出现元素O的位置,否则返回-1
Object remove(int index):删除指定位置上的元素
Object set(int index,Object element):用元素Element取代位置Index上的元素,并且返回旧的元素
2、List接口不但以位置序列迭代的遍历整个列表,还能处理集合的子集:
ListIterator ListIterator():返回一个列表迭代器,用来访问列表中的元素
ListIterator ListIterator(int index):返回一个列表迭代器,用来从指定位置Index开始访问列表中的元素
List subList(int formIndex,int toIndex):返回从指定位置FromIndex(包含)到ToIndex(不包含)范围中各个元素的列表视图
对子列表的更改对底层List也有影响。


ListIterator接口继承Iterator接口以支持添加或更改底层集体中的元素,还支持双向访问。ListIterator没有当前位置,光标位于调用

Previous和Next方法返回的值之间。一个长度为N的列表,有N+1个有效索引值:
1、Void add(Object o):将对象O添加到当前位置的前面
Void set(Object o):用对象O替代Next或Previous方法访问的上一个元素。如果上次调用后列表结构被修改了,那么将抛出

IIIegalStateException异常。

2、Boolean hasPrevious():判断向后迭代时是否有元素可访问
Object previous():返回上一个对象
Int nextIndex():返回下次调用Next方法时将返回的元素的索引
Int previousIndex():返回下次调用Previous方法时将返回的元素的索引

有两个抽象的List实现类:AbstractList和AbstractSequentialList。它们覆盖了Equals()和HashCode()方法以确保两个相等的集合返回相同

的哈希码。


在“集合框架”中有两种常规的List实现:ArrayList和LinkedList。如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么

,ArrayList提供了可选的集合。但如果,您要频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素,那么,LinkedList实现

更好。
ArrayList和LinkedList都实现Cloneable接口,都提供了两个构造函数,一个无参的,一个接受另一个Collection。


LinkedList类添加了一些处理列表两端元素的方法。
1、Void addFirst(Object o):将对象O添加到列表的开头。
Void addLast(Object o):将对象O添加到列表的结尾
2、Object getFirst():返回列表开关的元素
Object getLast():返回列表结尾的元素
3、Object removeFirst():删除并且返回列表开关的元素
Object removeLast():删除并且返回列表结尾的元素
4、LinkedList():构建一个空的链接列表
Linked(Collection c):构建一个链接列表,并且添加集合C的所有元素
使用这些新方法,您就可以轻松的把LinkedList当作一个堆栈、队列或其它面向端点的数据结构


ArrayList类封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个Capacity。这个Capacity表示存储列表中元素的数组的容量。

当元素添加到ArrayList时,它的Capacity在常量时间内自动增加。在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity方

法增加Capacity.这可以减少增加重分配的数量。
1、Void ensureCapacity(int minCapacity):将ArrayList对象容量增加MinCapacity
2、Void trimToSize():整理ArrayList对象容量为列表当前大小。程序可使用这个操作减少ArrayList对象存储空间。

 

Set接口继承Collection接口,而且它不允许集合中存在重复项,每个具体的Set实现类依赖添加的对象的Equals()方法来检查狂性。Set接口没

有引入新方法,所以Set就是一个Collection,只不过其行为不同。


Hash表是一种数据结构,用来查找对象。Hash表为每个对象计算出一个整数,称为Hash Code(哈希码)。Hash表是个链接式列表的阵列。每个

列表称为一个Buckets(哈希表元)。对象位置的计算Index=HashCode%buckets。

在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现Comparable接口以提供一定排序

方式,但这样只能实现该接口一次。对于那些没有实现Comparable接口的类、或者自定义的类,您可以通过Comparator接口来定义您自己的比

较方式。

在Java.lang包中,Comparable接口适用于一个类有自然顺序的时候。假定对象集合是同一个类型,该接口允许您把集合排序成自然顺序。
Int compareTo(Object o):比较当前实例对象与对象O,如果位于对象O之前,返回负值,如果两个对象在排序中位置相同,则返回0,如果位于

对象O后面,则返回正值。


SortedSet,它保持元素的有序顺序。SortedSet接口为集合的视图和它的两端提供了访问方法。当佻处理列表的子集时,理性视图会反映到源

集。此外,更改源集也会反映在子集上。发生这种情况的原因在于视图由两端的元素而不是下标元素指定,所以如果您想要一个特殊的高端元

素在子集中,您必须找到下一个元素。
添加到SortedSet实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个接口的实现。TreeSet类是它的唯一一分实现。
1、Comparator comparator():返回对元素进行排序时使用的比较器,如果使用Comparable接口的compareTo()方法对元素进行比较,则返回

Null。
2、Object first():返回有序集合中第一个元素。
3、Object last():返回有序集合中最后一个元素。
4、SortedSet subSet(Object fromElement,Object toElement):返回从formElement到ToElement范围内元素的SortedSet视图。
5、SortedSet headSet(Object toElemtn):返回SortedSet的一个视图,其内各元素皆小于Toelement
6、SortedSet tailSet(Object fromElement):返回SortedSet的一个视图,其内各元素皆大于或等于FromElement

AbstractSet类覆盖了Object类的equals()和hashCode()方法,以确保两个相等的集返回相同的哈希码。若两个集大小相等且包含相同元素,则

这两个集相等。按定义,集的哈希码是集中元素哈希码的总和。因此,不论集的内部顺序如何,两个相等的集合有相同的哈希码。

Object类
1、Boolean equals(Object obj):对两个对象进行比较,以便确定它们是否相同
2、Int hashCode():返回该对象的哈希码。相同的对象必须返回相同的哈希码


“集合框架”支持Set接口两种普通的实现:HashSet和TreeSet。HashSet存储重复自由的集合。当您要从集合中以有序的方式插入和抽取元素

时,TreeSet实现会有用处。为了能顺利进行,添加到TreeSet的元素必须是可排序的。

HashSet类
1、HashSet():构建一个空的哈希集
2、HashSet(Collection c):构建一个哈希集,并且添加集合C中所有元素
3、HashSet(int initialCapacity):构建一个拥有特定容量的空哈希集
4、HashSet(int initialCapacity,float loadFactor):构建一个拥有特定容量和加载因子的空哈希集。LoadFactor是0至1之间的一个数

TreeSet类
1、TreeSet():构建一个空的树集
2、TreeSet(Collection c):构建一个树集,并且添加集合C中所有元素
3、TreeSet(Comparator c):构建一个树集,并且使用特定的比较器对其元素进行排序
4、TreeSet(SortedSet S):构建一个树集,添加有序集合S中所有元素,并且使用与有序集合S相同的比较器排序。


LinkedHashSet的迭代器按照元素的插入顺序来访问各个元素。它提供了一个可以快速访问各个元素的有序集合。同时,它也增加了实现的代价

,因为哈希表元中的各个元素是通过双重链接式列表链接在的。
1、LinkedHashSet():构建一个空的链接式哈希集
2、LinkedHashSet(Collection c):构建一个链接式哈希集,并且添加集合C中所有元素
3、LinkedHashSet(int initialCapacity):构建一个拥有特定容量的空链接式哈希集
4、LinkedHashSet(int initialCapacity,float loadFactor):构建一个拥有特定容量和加载因子的空链接式哈希集。LoadFactor是0至1之间的

一个数。

 

Map接口用于维护键/值对。该接口描述了从不重复的键到值的映射
1、添加、删除操作
Object put(Object key,Object value):将互相关联的一个关键字与一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值

将取代旧值。方法返回关键字的旧值,如果关键字原先并不存在,则返回Null
Object remove(Object key):从映像中删除与Key相关的映射
Void putAll(Map t):将来自特定映像的所有元素添加到该映像
Void clear():从映像中删除所有映射
2、查询操作:
Object get(Object key):获得与关键字Key相关的值,并且返回与关键字Key相关的对象,如果没有在该映像中找到该关键字,则返回Null
Boolean containsKey(Object key):判断映像中是否存在关键字Key
Boolean containsValue(Object value):判断映像中是否存在值Value
Int size():返回当前映像中映射的数量
Boolean isEmpty():判断映像中是否有任何映射
3、视图操作:处理映像中键/值对组
Set keySet():返回映像中所有关键字的视图集
Collection values():返回映像中所有值的视图集
Set entrySet():返回Map.Entry对象的视图集,即映像中的关键字/值对


Map的entrySet()方法返回一个实现Map.Entry接口的对象集合。集合中每个对象都是底层Map中一个特定的键/值对。
通过这个集合的迭代器,您可以获得每一个条目的键或值并对值进行更改。当条目通过迭代器返回后,除非是迭代器自身的remove()方法或者

迭代器返回的条目的setValue()方法,其余对源Map外部的修改都会导致此条目集变得无效,同时产生条目行为未定义。
Object getKey():返回条目的关键字
Object getValue():返回条目的值
Obect setValue(Object value):将相关映像中的值改为value,并且返回旧值。
 “集合框架”提供了个特殊的Map接口:SortedMap,它用来保持键的有序顺序。
  SortedMap接口为映像的视图(子集),包括两个端点提供了访问方法。除了排序是作用于映射的键以外,处理SortedMap和处理SortedSet一

样。

  添加到SortedMap实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个Comparator接口的实现。TreeMap类是它的

唯一一份实现。

  “因为对于映射来说,每个键只能对应一个值,如果在添加一个键/值对时比较两个键产生了0返回值(通过Comparable的compareTo()方法

或通过Comparator的compare()方法),那么,原始键对应值被新的值替代。如果两个元素相等,那还好。但如果不相等,那么您就应该修改比

较方法,让比较方法和 equals() 的效果一致。”

  (1) Comparator comparator(): 返回对关键字进行排序时使用的比较器,如果使用Comparable接口的compareTo()方法对关键字进行比较

,则返回null

  (2) Object firstKey(): 返回映像中第一个(最低)关键字

  (3) Object lastKey(): 返回映像中最后一个(最高)关键字

  (4) SortedMap subMap(Object fromKey, Object toKey): 返回从fromKey(包括)至toKey(不包括)范围内元素的SortedMap视图(子集)

  (5) SortedMap headMap(Object toKey): 返回SortedMap的一个视图,其内各元素的key皆小于toKey

  (6) SortedSet tailMap(Object fromKey): 返回SortedMap的一个视图,其内各元素的key皆大于或等于fromKey

  4.3. AbstractMap抽象类

  和其它抽象集合实现相似,AbstractMap 类覆盖了equals()和hashCode()方法以确保两个相等映射返回相同的哈希码。如果两个映射大小

相等、包含同样的键且每个键在这两个映射中对应的值都相同,则这两个映射相等。映射的哈希码是映射元素哈希码的总和,其中每个元素是

Map.Entry接口的一个实现。因此,不论映射内部顺序如何,两个相等映射会报告相同的哈希码。

  4.4. HashMap类和TreeMap类

  “集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。在Map 中插入、删除和定位元素,HashMap 是

最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和equals

()的实现。

  这个TreeMap没有调优选项,因为该树总处于平衡状态。
  4.4.1. HashMap类

  为了优化HashMap空间的使用,您可以调优初始容量和负载因子。

  (1) HashMap(): 构建一个空的哈希映像

  (2) HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射

  (3) HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像

  (4) HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像

  4.4.2. TreeMap类

  TreeMap没有调优选项,因为该树总处于平衡状态。

  (1) TreeMap():构建一个空的映像树

  (2) TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素

  (3) TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序

  (4) TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序

  4.5. LinkedHashMap类

  LinkedHashMap扩展HashMap,以插入顺序将关键字/值对添加进链接哈希映像中。象LinkedHashSet一样,LinkedHashMap内部也采用双重链

接式列表。

  (1) LinkedHashMap(): 构建一个空链接哈希映像

  (2) LinkedHashMap(Map m): 构建一个链接哈希映像,并且添加映像m中所有映射

  (3) LinkedHashMap(int initialCapacity): 构建一个拥有特定容量的空的链接哈希映像

  (4) LinkedHashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的链接哈希映像

  (5) LinkedHashMap(int initialCapacity, float loadFactor,

  boolean accessOrder): 构建一个拥有特定容量、加载因子和访问顺序排序的空的链接哈希映像

  “如果将accessOrder设置为true,那么链接哈希映像将使用访问顺序而不是插入顺序来迭

  代各个映像。每次调用get或者put方法时,相关的映射便从它的当前位置上删除,然后放到链接式映像列表的结尾处(只有链接式映像列

表中的位置才会受到影响,哈希表元则不受影响。哈希表映射总是待在对应于关键字的哈希码的哈希表元中)。”

  “该特性对于实现高速缓存的“删除最近最少使用”的原则很有用。例如,你可以希望将最常访问的映射保存在内存中,并且从数据库中

读取不经常访问的对象。当你在表中找不到某个映射,并且该表中的映射已经放得非常满时,你可以让迭代器进入该表,将它枚举的开头几个

映射删除掉。这些是最近最少使用的映射。”

  (6) protected boolean removeEldestEntry(Map.Entry eldest): 如果你想删除最老的映射,则覆盖该方法,以便返回true。当某个映射

已经添加给映像之后,便调用该方法。它的默认实现方法返回false,表示默认条件下老的映射没有被删除。但是你可以重新定义本方法,以便

有选择地在最老的映射符合某个条件,或者映像超过了某个大小时,返回true。

  4.6. WeakHashMap类

  WeakHashMap是Map的一个特殊实现,它使用WeakReference(弱引用)来存放哈希表关键字。使用这种方式时,当映射的键在 WeakHashMap

的外部不再被引用时,垃圾收集器会将它回收,但它将把到达该对象的弱引用纳入一个队列。WeakHashMap的运行将定期检查该队列,以便找出

新到达的弱应用。当一个弱引用到达该队列时,就表示关键字不再被任何人使用,并且它已经被收集起来。然后WeakHashMap便删除相关的映射

  (1) WeakHashMap(): 构建一个空弱哈希映像

  (2) WeakHashMap(Map t): 构建一个弱哈希映像,并且添加映像t中所有映射

  (3) WeakHashMap(int initialCapacity): 构建一个拥有特定容量的空的弱哈希映像

  (4) WeakHashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的弱哈希映像

  4.6. IdentityHashMap类

  IdentityHashMap也是Map的一个特殊实现。在这个类中,关键字的哈希码不应该由hashCode()方法来计算,而应该由

System.identityHashCode方法进行计算(即使已经重新定义了hashCode方法)。这是Object.hashCode根据对象的内存地址来计算哈希码时使用

的方法。另外,为了对各个对象进行比较,IdentityHashMap将使用==,而不使用equals方法。

  换句话说,不同的关键字对象,即使它们的内容相同,也被视为不同的对象。IdentityHashMap类可以用于实现对象拓扑结构转换

(topology-preserving object graph transformations)(比如实现对象的串行化或深度拷贝),在进行转换时,需要一个“节点表”跟踪那些

已经处理过的对象的引用。即使碰巧有对象相等,“节点表”也不应视其相等。另一个应用是维护代理对象。比如,调试工具希望在程序调试

期间维护每个对象的一个代理对象。

  “IdentityHashMap类不是一般意义的Map实现!它的实现有意的违背了Map接口要求通过equals方法比较对象的约定。这个类仅使用在很少

发生的需要强调等同性语义的情况。”

  (1) IdentityHashMap (): 构建一个空的全同哈希映像,默认预期最大尺寸为21

  “预期最大尺寸是映像期望把持的键/值映射的最大数目”

  (2) IdentityHashMap (Map m): 构建一个全同哈希映像,并且添加映像m中所有映射

  (3) IdentityHashMap (int expectedMaxSize): 构建一个拥有预期最大尺寸的空的全同哈希映像。放置超过预期最大尺寸的键/值映射时

,将引起内部数据结构的增长,有时可能很费时

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值