集合框架.docx
- 文档编号:6900561
- 上传时间:2023-01-12
- 格式:DOCX
- 页数:27
- 大小:32.46KB
集合框架.docx
《集合框架.docx》由会员分享,可在线阅读,更多相关《集合框架.docx(27页珍藏版)》请在冰豆网上搜索。
集合框架
第1章集合框架
⊙学习目标
◎了解什么是集合框架
◎了解常用的集合接口
◎掌握常用的集合类
1.1集合简介
在前面学习了Java数组,Java数组的长度是固定的,在同一个数组中只能存放相同类型的数据。
数组可以存放基本类型的数据,也可以存放引用类型的数据。
在创建Java数组时,必须明确指定数组的长度。
数组一旦创建,其长度就不能被改变。
在许多应用中,一组数据的数目是不固定的。
比如一个单位的员工数目是变化的。
有老员工跳槽,也有新员工进来。
为了使程序能方便地存储和操纵数目不固定的一组数据,JDK类库提供了Java集合,所有Java集合类都位于java.util包中。
与Java数组不同,Java集合中不能存放基本数据类型数据,而只能存放对象的引用。
1.1.1.什么是集合
通常情况下,把具有相同性质的一类东西汇聚成一个整体,就可以成为集合。
比如,用Java编程的所有程序员和全体中国人等。
通常集合有两种表示方法,一种是列举法,比如集合A={1,2,3,4},另一种是性质描述法,比如集合B={X|0 1.1.2.什么是集合框架 那么有了集合的概念,什么是集合框架呢? 集合框架就是为了表示和操作集合而规定的一种统一的标准的体系结构。 任何集合框架都包含三大块内容: 对外的接口、接口的实现和对集合运算的算法。 Ø接口: 即表示集合的抽象数据类型。 接口提供了让我们对集合中所表示的内容进行单独操作的可能 Ø实现: 也就是集合框架中接口的具体实现。 实际它们就是那些可复用的数据结构。 Ø算法: 在一个实现了某个集合框架中的接口的对象上完成某种有用的计算方法,例如查找。 排序等。 这些算法通常是多态的,因为相同的方法可以再同一个接口被多个类实现时有不同的表现。 事实上,算法是可复用的函数。 1.1.3集合框架的好处 1、它减少了程序设计的辛劳 集合框架通过提供有用的数据结构和算法使我们能集中注意力于重要部分上,而不是为了让程序能正常运转而将注意力集中于底层设计上。 通过这些在无关API之间的简易的互用性,使我们免除了为改变对象或转换代码以便联合这些API而去写大量的代码。 2、它提高了程序速度和质量 集合框架通过提供对有用的数据结构和算法的高性能和高质量的实现,这使我们的程序速度和质量得到提高。 因为每个接口的实现是可互换的,所以我们的程序可以很容易的通过改变一个实现而进行调整。 另外,我们将可以从自己的数据结构的同差事中解脱出来,从而有更多时间关注于程序其他部分的质量和性能。 3、减少去学习和使用新的API的辛劳 许多API有对集合的存储和获取。 在过去,这样的API都有一些子API帮助操纵它的集合内容,因此在那些特殊的子API之间就会缺乏一致性,你也不得不从零开始学习,并且在使用时也很容易犯错。 而标准集合框架接口的出现使这个问题迎刃而解。 4、减少了设计新API的努力 设计者和实现者不用在每次创建一种依赖于集合内容的API时重新设计,他们只要使用标准集合框架的接口即可。 5、集合框架鼓励软件的复用 对于遵照标准集合框架接口的新的数据结构是可复用的。 同样对于操作一个实现了这些接口的对象的算法也是如此。 有了这些优点,并通过合理的使用,它就会成为程序员的一种强大的工具,不过,从历史来看,集合大多其结构相当复杂,也就给它们一个造成极不合理的学习曲线的坏名声。 但是,Java的集合框架能缩短我们的学习曲线,从而快速掌握它。 在许多高级语言中的数组其实也是集合的一种简单实现,比如C,C++,Pascal和Java。 数组保存着相同类型的多个值,它的长度在数组呗创建时就固定写来,建立之后就无法改变。 如果你需要一种大小能动态改变的存储结构,数组就不合适了,这时集合框架就有用武之地了。 1.2常用的集合接口 1.2.1集合框架的类图 Java平台提供了一个全新的集合框架。 “集合框架”主要由一组用来操作对象的接口组成,不同接口描述一组不同的数据类型。 Java集合框架在设计时大量使用了接口和抽象类,这使得集合框架具有良好的扩展性。 接口、集合算法和接口是实现是Java集合框架的主要组成部分,Java集合框架如图1-1所示。 图1-1集合框架图 在很大程度上,一旦理解了接口,我们就理解了框架。 虽然我们总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上;因此,允许更改基本的数据结构而不必改变其它的代码。 ØCollection接口: 表示一组对象,这些对象也称为collection的元素。 一些collection允许有重复的元素,而另一些则不允许。 一些collection是有序的,而另一些则是无序的。 ØSet接口继承Collection,但不允许重复,使用自己内部的一个排列机制(无序)。 ØList接口继承Collection,允许重复,以元素安插的次序来放置元素,不会重新排列(有序)。 ØMap接口是一组成对的键-值对象,即所持有的是key-value对。 Map中不能有重复的key。 拥有自己的内部排列机制(无序)。 Ø容器中的元素类型都为Object。 从容器中取得元素时,必须把它转换成原来的类型。 1.2.2Collection接口 用于表示任何对象或元素组。 想要尽可能以常规方式处理一组元素时,就使用这一接口。 显然,既然用集合能做这些事情,那么用一个Set或者List同样也能做到。 List还增加了一些新的功能,而Map由于不是从集合继承的,所以要单独对待。 下面是介绍Collection下的常用方法,见表1-1。 表1-1集合的常用方法 方法名称 描述 booleanadd(Objecto) 将对象添加到集合 booleanremove(Objecto) 如果集合中有与o相匹配的对象,则删除对象o intsize() 返回当前集合中元素的数量 booleanisEmpty() 判断集合中是否有任何元素 booleancontains(Objecto) 查找集合中是否含有对象o Iteratoriterator() 返回一个迭代器,用来访问集合中的各个元素 booleancontainsAll(Collectionc) 查找集合中是否含有集合c中所有的元素 booleanaddAll(Collectionc) 将集合c中所有元素添加到该集合 voidClear() 删除集合中所有元素 voidremoveAll(Collectionc) 从集合中删除集合c中的所有元素 voidretainAll(Collectionc) 从集合中删除集合c不包含的元素 Object[]toArray() 返回一个内含集合所有元素的array Object[]toArray(Object[]a) 以数组的形式返回集合中与数组a类型匹配的元素 此外,还可以把集合转换成其他任何的对象数组。 但是,不能直接把集合转换成原始数据类型的数组,因为集合必须持有对象。 有些方法是可选的。 因为实现一个接口必须实现所有接口方法,调用程序就需要一种途径来知道一个可选的方法是不是不受支持。 如果调用一种可选方法时,一个UnsupportedOperationException被抛出,则操作失败,因为方法不受支持。 此异常类继承RuntimeException类,避免了将所有集合操作放入try-catch块。 Collection不提供get()方法。 如果要遍历Collection中的元素,就必须用Iterator(迭代器)。 1.2.3List List接口继承了Collection接口以定义一个允许重复项的有序集合。 该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。 另外List实际有两种类型,其中包括最基本的ArrayList,它擅长于对元素的随机访问。 以及功能更强大的LinkedList,用它进行随机访问的效率并不高,但它提供的方法要丰富的多。 List接口与常用实现类介绍见表1-2。 表1-2List接口 List接口 顺序是List最重要的特性,它可以保证元素按规定的顺序排列。 List为Collection添加了大量的方法,以便我们在List的中部插入和删除元素。 只推荐对LinkedList这样做,List也会生产一个ListIterator列表迭代器,利用它可在一个List里朝两个方向巡视,同时插入和删除位于List中部的元素。 ArrayList类 由一个数组实现的List,可对元素进行速度非常快的随机访问。 但用它在List中部插入或删除元素的时候速度却比较慢,ListIterator通常只能用于在一个ArrayList中来回“遍历”,而不要用它插入或删除元素。 LinkedList类 提供优化的顺序访问性能,同时可以高效的在List中部进行插入和删除操作,但在进行随机访问时速度却相当慢,此时应换用ArrayList。 另外它还提供了addFirst()、addLast()、getFirst()、getLast()、removeFirst()以及removeLast()等方法,这些方法在任何接口或基类中均未定义,适用于对堆栈队列以及双头队列进行操作。 面向位置的操作包括插入某个元素或收集的功能,还包括获取、除去或更改元素的功能。 在List中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。 List的常用方法见表1-3. 表1-3List的常用方法 方法名称 描述 voidadd(intindex,Objectelement) 在指定位置index上添加元素element booleanaddAll(intindex,Collectionc) 将集合c的所有元素添加到指定位置index Objectget(intindex) 返回List中指定位置的元素 intindexOf(Objecto) 返回第一个出现元素o的位置,否则返回-1 intlastIndexOf(Objecto) 返回最后一个出现o元素的位置,否则返回-1 Objectremove(intindex) 删除指定位置上的元素 Objectset(intindex,Objectelement) 用元素element取代位置index上的元素,并且返回旧的元素 ListIteratorlistIterator() 返回一个列表迭代器,用来访问列表中的元素 ListIteratorlistIterator(intindex) 返回一个列表迭代器,用来从指定位置index开始访问列表中的元素 ListsubList(intfromIndex,inttoIndex) 返回从指定位置fromIndex(包含)到toIndex(不包含)范围中的各个列表视图。 对子列表的更改(比如add()、remove()、set()调用)对底层List也有影响。 1.2.4Set Set接口继承Collection接口,而且它不允许集合中存在重复项,每个具体的Set实现类依赖添加的对象的equals()方法来检查独一性。 Set接口没有引入新方法,所以Set就是一个Collection,只不过其行为不同。 Set接口及其常用实现类见表1-4. 表1-4Set集合 Set接口 添加到Set的每个元素都必须是独一无二的,Set不会添加重复的元素,添加到Set里的对象必须定义equals()以树立对象的“唯一”性。 Set拥有与Collection完全相同的接口,Set接口并不保证自己会按任何特定的顺序来容纳元素。 HashSet类 假如在一个Set中的搜索速度是至关重要的,就应考虑用HashSet,同时Object还必须定义hashCode() TreeSet类 排好序的一种Set,采用树形结构,这样一来就可从Set里提取出一个固定顺序的元素序列。 1.2.5Map Map(映射)是一种把键对象和值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象。 向Map集合加入元素时,必须提供一对键对象和值对象。 从Map集合中检索元素时,只要给出键对象,就会返回值对象。 Map接口不是Collection接口的继承。 Map接口用于维护键/值对(key/value)。 该接口描述了从不重复的键到值的映射,Map接口及其实现介绍见表1-5。 表1-5Map集合 Map接口 维持“键值”对应关系对以便根据一个键查找到相应的值。 HashMap 基于一个散列表实现,用它代替HashTable针对“键值”对的插入和检索。 这种形式具有最稳定,但不是最好的性能。 可通过构造函数设置散列表的“容量”与“负载比”,从而对性能进行调整 TreeMap 在一个“红黑”树的基础上实现查看键或者“键值”对时,它们会按固定的顺序排列。 取决于Comparable或Comparator,稍后即会讲到TreeMap最大的好处就是我们得到的是已排好序的结果。 TreeMap是提供了subMap()方法的唯一一种Map,用它可返回树的一部分子映射。 Map接口常用方法见表1-6。 表1-6Map集合的常用方法 方法名称 描述 Objectput(Objectkey,Objectvalue) 将互相关联的一个关键字与一个值放入该映像。 如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。 方法返回关键字的旧值,如果原先不存在,则返回null Objectremove(Objectkey) 从映像中删除与key相关的映射 voidputAll(Mapt) 将来自特定映像的所有元素添加到该映像 voidclear() 从映像中删除所有映射,键和值都可以为null。 但是不能把Map作为一个键或值添加给自身 Objectget(Objectkey) 获得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有在该映像中找到该关键字,则返回null booleancontainsKey(Objectkey) 判断映像中是否存在关键字key booleancontainsValue(Objectvalue) 判断映像中是否存在值value intsize() 返回当前映像中映射的数量 booleanisEmpty() 判断映像中是否有任何映射 SetKeySet() 返回映像中所有关键字的视图集,因为映射中键的集合必须是唯一的。 还可以从视图中删除元素,同时,关键字和它相关的值将从源映像中被删除,但是你不能添加任何元素 Collectionvalues() 返回映像中所有值的视图集,因为映射中值的集合不是唯一的,您用Collection支持。 还可以从视图中删除元素,同时,值和它的关键字将从源映像中被删除,但是你不能添加任何元素。 SetentrySet() 返回Map.Entry对象的视图集,即映像中的关键字/值对,因为映射是唯一的,您用Set支持。 还可以从视图中删除元素,同时,这些元素将从源映像中被删除,但是不能添加任何元素。 1、Hash表 Hash表是一种数据结构,用来查找对象。 Hash表为每个对象计算出一个整数,称为HashCode(哈希码)。 Hash表是个链接式列表的阵列。 每个列表称为一个buckets(哈希表元)。 对象位置的计算index=HashCode%buckets(HashCode为对象哈希码,buckets为哈希表元总数)。 当添加元素时,有时会遇到已经填充了元素的哈希表元,这种情况称为HashCollisions(哈希冲突)。 这时,就必须判断该元素是否已经存在于该哈希表中。 如果哈希码是合理的随机的分布的,并且哈希表元的数量足够大,那么哈希冲突的数量就会减少。 同时,也可以通过设定一个初始的哈希表元数量来更好的控制哈希表的运行。 初始哈希表元的数量为buckets=size*150%+1(size为预期元素的数量)。 如果哈希表中的元素放得太满,就必须进行rehashing(再哈希)。 再哈希是哈希表元数增倍,并将原有的对象重新导入新的哈希表元中,而原始的哈希表元被删除。 Loadfactor(加载因子)决定何时要对哈希表进行再哈希。 在Java编程语言中,加载因子默认值为0.75,默认哈希表元101. 2、Comparable接口和Comparator接口 在“集合框架”中有两种比较接口: Comparable接口和Comparator接口。 像String和Integer等Java内建类实现Comparable接口以提供一定排序方式,但这样只能实现该接口一次。 对于那些没有实现Comparable接口的类、或者自定义的类,可以通过Comparator接口来定义自己的比较方式。 1.2.6Iterator Collection接口的iterator()方法返回一个Iterator。 Iterator接口方法能以迭代方式逐个访问集合中各个元素,并安全的从Collection中除去适当的元素。 Iterator常用方法见表1-7. 表1-7Iterator常用方法 方法名称 描述 booleanhasNext() 判断是否存在另一个可访问的元素 Objectnext() 返回要访问的下一个元素。 如果达到集合结尾,则抛出NoSuchElementException异常 voidremove() 删除上次访问返回的对象。 本方法必须紧跟在一个元素的访问后执行。 如果上次访问后集合已被修改,方法将抛出IllegalStateException。 Iterator中删除操作对底层Collection也有影响。 迭代器是故障快速修复(fail-fast)的。 这意味着,当另一个线程修改底层集合的时候,如果正在用Iterator遍历集合,那么Iterator就会抛出ConcurrentModificationException异常,并立刻执行失败。 1.3常用集合类 1.3.1Iterator Iterator用于对集合容器进行向前的单方向遍历,通常称作迭代器。 Iterator模式是用于遍历集合类的标准访问方法。 它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。 如何遍历Collection中每一个元素? 不论Collection的实际类型如何,它都支持一个iterator()方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。 典型的用法如下: ...... Iteratorit=Collection.iterator();//获得一个迭代子 While(it.hasNext()){ Objectobj=it.next();//得到下一个元素 } ...... 在上面的例子中,我们也可以用Iterator进行迭代。 如例1-1所示。 例1-1: importjava.util.*; publicclassTestIterator1_1{ /** *这个类演示Iterator的用法 * *@version0.1,31/3/2012 *@authorwangsen */ publicstaticvoidmain(String[]args){ Listlist=newArrayList();//创建并初始化一个List数组 //用add()方法可以将一个对象加入ArrayList数组中 list.add("a"); list.add("b"); list.add("c"); Iteratoriter=list.iterator();//使用iterator()取得元素 while(iter.hasNext()){//hasNext()是否还有下一个元素 //使用next()取得下一个元素 System.out.println(iter.next()); } } } 执行上面程序运行结果如: a b c 1.3.2ArrayList类和LinkedList类 在“集合框架”中有两种常规的List实现: ArrayList和LinkedList。 使用两种List实现的哪一种取决于我们的需要。 如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么,ArrayList提供了可选的集合。 但如果要频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素,那么使用LinkedList实现更好。 1、ArrayList类 ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。 数组的缺点是每个元素之间不能含有“空隙”,当数组大小不满足时,需要增加存储空间,就要将已有数组数据复制到新的存储空间中。 当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动,代价比较高。 因此,它适合随机查找和遍历,不适合插入和删除。 ArrayList的实质就是一个自动增长的数组。 它是用封装的数组来实现的List接口,底层用数组实现。 随着向ArrayList中不断添加元素,其容量会自动增长。 创建一个ArrayList类的实例,可以使用如下构造方法。 见表1-8 表1-8ArrayList类的构造方法 构造方法 说明 ArrayList() 创建一个空的ArrayList对象 ArrayList(intsize) 创建一个指定大小的ArrayList对象 ArrayList(Collectionc) 创建指定集合的ArrayList对象 ArrayList类的常用方法见表1-9. 方法 说明 Object[]toArray() 以数组形式返回ArrayList中的元素 intsize() 返回当前ArrayList中元素的数量 booleanadd(Objecto) 将对象添加到ArrayList的最后 booleanadd(intindex,Objecto) 在指定位置上添加o元素 booleanaddAll(Collectionc) 将集合c中的所有元素添加到ArrayList的最后 Objectget(intindex) 返回ArrayList中指定位置的元素 intindexOf(Objecto) 返回第一个出现元素o的位置,否则返回-1 intlastIndexOf(Objecto) 返回最后一个出现元素o的位置,否则返回-1 Objectremove(intindex) 删除指定位置上的元素 Objectset(intindex,Objectelement) 用元素element取代位置index上的元素,并且返回被取代的元素 Iteratoriterator() 返回一个迭代器,用来访问ArrayList中的各个元素 ArrayList类封装了一个动态再分配的Object[]数组。 每个ArrayList对象有一个容量。 它表示存储列表中元素的数组的容量。 当元素添加到ArrayList时,它的容量在常量时间内自动增加。 如例1-2演示ArrayList的部分方法。 例1-2: importjava.util.*; publicclassTestArrayList1_2{ /** *这个类演示
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 集合 框架