Java编程思想第11章持有对象.ppt_第1页
Java编程思想第11章持有对象.ppt_第2页
Java编程思想第11章持有对象.ppt_第3页
Java编程思想第11章持有对象.ppt_第4页
Java编程思想第11章持有对象.ppt_第5页
已阅读5页,还剩97页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第十一章持有对象,泛型Collection家族和Map家族的其它成员迭代器,一、为什么要引入容器类?,1、在编程中经常会遇到这样的问题:需要在任意时刻和任意位置创建任意数量的对象我们不能像往常一样,依靠创建命名的引用来持有每一个对象,2、数组是编译器支持的类型,很高效,但不够灵活(固定大小和固定类型)这带来一个问题:在写程序时,你并不知道将需要多少个对象,或者是否需要更复杂的方式来存储对象,一、为什么要引入容器类?,3、Java内库提供一套相当完整的容器类来解决这些问题例如:List、Set、Queue和Map在这些容器类中,Java提供了许多非常有用的工具,一、为什么要引入容器类?,1、泛型(Generics)的概念泛型是指通过参数化类型,使代码适用于许许多多的类型复习:C+中的类模板,二、泛型和类型安全的容器,2、使用预定义的泛型典例分析:ArrayListapples仔细分析该代码的完整含义,二、泛型和类型安全的容器,典例分析:ArrayListapples1、首先分析:ArrayListapplesinti;/声明一个整型变量iArrayListapples;/声明一个ArrayList类的对象apples,2、其次,我们注意到:在Java中,所有对对象的操纵都必须通过引用所以,声明一个ArrayList类的对象apples更准确的描述应该是:声明一个指向ArrayList类对象的引用apples,3、最后,完整分析:ArrayListapples声明一个指向ArrayList类对象的引用apples而该ArrayList容器用来保存Apple对象,/下面是完整程序,参见P217classAppleclassOrangepublicclassApplesWithGenericspublicstaticvoidmain(Stringargs),ArrayListapples=newArrayList();new关键字的重要作用:申请存储空间创建对象并使用构造函数初始化返回指向该对象的一个引用,for(inti=0;i3;i+)apples.add(newApple);类型安全是指不能加入其它类型可以任意添加Apple对象但是不能添加Orange对象,JavaSE5之前的容器存在的问题:以前容器保存的是Object对象,所以编译时允许向容器中添加不正确的类型但这会产生运行时异常JavaSE5引入泛型(Generics),可以解决这个问题,泛型机制将运行时异常转变为编译时错误,归纳:使用泛型的优点编译器可以检查放置到容器中的对象类型使用容器中的对象时,可以使用更加清晰的语法(例如:不需要强制转型,更清晰的使用foreach)向上转型也可以在泛型中很好的工作,/使用传统的语法for(inti=0;iapples.size();i+)print(apples.get(i);/使用更为方便的Foreach语法for(Applec:apples)print();,1、Collection家族和Map家族Map接口:一组成对的键值对对象Map是强大的编程工具,也称为字典,因为你可以使用键对象来查找值对象,三、基本概念,2、使用接口的一般方式创建一个具体类的对象,将其向上转型为对应的接口,然后在其余的代码中都使用这个接口,三、基本概念,典例分析:Listapples=newLinkedList()1、首先分析:Listapples声明一个指向实现了List接口的类对象的引用apples简称为:声明一个指向List接口的引用apples,典例分析:Listapples=newLinkedList()2、其次分析:Listapples声明一个指向List接口的引用apples该List容器用来保存Apple对象,典例分析:Listapples=newLinkedList()3、再其次分析:=newLinkedList()申请存储空间创建对象并使用构造函数初始化返回指向该对象的一个引用,典例分析:Listapples=newLinkedList()4、最后,综合分析和归纳如下:创建对象并返回对该对象的引用将该引用(所指向的对象)向上转型为:指向List接口的引用(所指向的对象),特别提醒:这种方式并非总能奏效,因为某些类具有额外的功能例如:LinkedList具有在List接口中并未包含的额外方法所以,如果你需要使用这些方法,就不能将它们向上转型为更通用的接口,/完整的程序,参见P219publicclassSimpleCollectionpublicstaticvoidmain(Stringargs)Collectionc=newArrayList();/参照前面分析,仔细分析这段代码,for(inti=0;i10;i+)/自动包装:将普通整型包装为类c.add(i);/使用Foreach语法for(Integeri:c)/自动拆包:将类转换为普通整型System.out.println(i+“,”);,3、泛型中的向上转型向上转型为基类的对象典例分析:详见P218代码,三、基本概念,classGrannySmithextendsAppleclassFujiextendsAppleclassBraeburnextendsApple/在欧洲和北美,顾客选择的品种不过几种:澳洲青苹果(GrannySmith,别名史密斯)、富士、布雷伯博恩(Braeburn),publicclassGenericsAndUpcastingpublicstaticvoidmain(Stringargs)ArrayListapples=newArrayList();apples.add(newGrannySmith();apples.add(newFuji();apples.add(newBraeburn();/可以将Apple的子类型添加到:被指定为保存Apple对象的容器中,归纳:与前面向上转型的区别前者:将创建的对象向上转型为实现其父类接口的类的对象,并没有涉及到泛型后者:在泛型中使用向上转型,1、Arrays类Arrays类的概念Arrays类定义了对数组进行的各种各样操作(如查询、排序等等),四、Arrays类和Collections类,Arrays类的声明publicclassArraysextendsObject,四、Arrays类和Collections类,Arrays类的105个方法更详细资料请参阅官方文档,四、Arrays类和Collections类,1、publicstaticListasList(T.A)首先分析:Arrays.asList()方法的参数T.A表示可变参数所以,该方法可以接收的参数是:一个数组或者是用一个逗号分隔的元素列表,其次分析:Arrays.asList()方法的返回值返回一个定长的List,所以不能再将它转换为ArrayList(可变长数组)原因:asList()方法返回的只是数组的另一个视图,然而底层的数组本身却并没有发生改变,对List的任何操作最终都要反映在该底层数组上,所以不支持remove、add方法,最后分析:Arrays.asList()方法的作用它是基于Arrays的API和基于Collection的API之间相互转换的一个桥梁它提供了创建定长List的一种方便形式,例如Liststooges=Arrays.asList(“Larry”,“Moe”,“Curly”);,2、staticintbinarySearch(floata,floatkey)利用折半查找法查找指定float数组中的指定值Arrays共有18个binarySearch重载方法,主要是提供各种各样的参数以及变型(例如在指定范围执行二分查找),3、staticbooleancopyOf(booleanoriginal,intnewLength)Copiesthespecifiedarray,truncatingorpaddingwithfalse(ifnecessary)sothecopyhasthespecifiedlengthArrays共重载了20种数组拷贝的方法,4、大量的equals()方法Returnstrueifthetwospecifiedarraysofbooleanareequaltooneanother比较指定的两个数组是否相等5、大量的fill()方法将指定的值替换指定的数组元素,6、大量的sort()方法按照升序或降序对数组元素进行排列7、大量的toString()方法Returnsastringrepresentationofthecontentsofthespecifiedarray将指定数组的内容转换为一个字符串,2、Collections类Collections类的概念该类完全由在collection上进行操作或者返回collection的静态方法组成,四、Arrays类和Collections类,Collection和Collections的区别1、Collection是java.util下的接口,是各种集合结构的父接口;该接口的意义是为各种具体的集合提供了最大程度的统一操作方式2、Collections是java.util下的类,里面包含各种有关集合操作的静态方法;该类不能实例化,就像一个工具类,服务于Java的Collection框架,Collections类的声明publicclassCollectionsextendsObject,四、Arrays类和Collections类,Collections类的52个方法更详细资料请参阅官方文档,四、Arrays类和Collections类,1、publicstaticbooleanaddAll(Collectionc,T.Elements)将所有指定的元素添加到指定的Collection使用可变参数,将要添加的元素要么是用一个逗号分隔的元素列表,要么是一个数组,当将要添加的元素是用一个逗号分隔的参数列表,该方法提供了一个简便的方式,用来将这些元素添加到指定的Collection典例分析:Collections.addAll(flavors,“PeachesnPlutonium”,“RockyRacoon”);,Collections.addAll()方法与Arrays.asList()方法的异同点相同:同样使用可变参数,将数组或用逗号分隔的参数列表添加到Collection注意:List实质上也是一个Collection不同:但在很多情况下,前者的速度要快得多,2、剩下的方法不再介绍有网友给出了一个非常好的学习笔记,里面不但给出了很多方法的详细解释,并且还有相关例程加以说明网址:http:/gym-,3、应用典例:添加一组元素参见P220代码,四、Arrays类和Collections类,publicclassAddingGroupspublicstaticvoidmain(Stringargs)Collectioncollection=newArrayList(Arrays.asList(1,2,3,4,5);这条语句非常复杂,我们逐一进行分析,Arrays.asList()方法:从前面的分析可知:该方法接受一个数组或者是用一个逗号分隔的元素列表,并将其转换为一个定长的List对象,Collection的构造器:该构造器可以接受另外一个Collection作为参数,用它来将自身初始化因此,你可以使用Arrays.asList为这个构造器提供输入(Collection可以这样做,意味着所有实现Collection接口的集合类也可以),综合分析:创建对象并返回对该对象的引用collection最后,向上转型为指向Collection接口的引用,IntegermoreInts=6,7,8,9,10;创建引用数组(指向Integer对象的引用数组)并初始化JavaSE5以后的版本提供该支持,Collections.addAll(collection,11,12,13,14,15);Collections.addAll(collection,moreInts);参见前面分析的Collections.addAll()方法:Collections.addAll()方法接受一个Collection对象,以及一个数组或者是一个用逗号分隔的列表,将元素添加到Collection中,collection.addAll(Arrays.asList(moreInts);Collection.addAll()只能接受另一个Collection对象作为参数,因此不如Arrays.asList()或者Collections.addAll()灵活,后两个方法都可以使用可变参数列表但是它的速度更加快,因此是首选方式,Listlist=Arrays.asList(16,17,18,19,20);/Arrays.asList()方法的底层实现是数组list.set(1,99);/OK-modifyanelementlist.add(21);/Runtimeerror(定长List),1、ArrayList的优缺点优点:随机访问缺点:插入、删除和移动元素较慢,五、List接口的总结,2、LinkedList的优缺点同ArrayList相反注意:LinkedList的方法集(39个方法)比ArrayList(20个方法)的更大,五、List接口的总结,1、迭代器(Iterator)的概念迭代器是一个对象主要作用是:用来抓取容器中的元素,并将抓取到的元素提交给迭代器用户,六、迭代器,迭代器的优点:利用迭代器,我们可以非常方便的遍历整个容器中的对象序列,而不用关心底层的结构是什么也就是说,客户端程序员不用去关心容器中的这个对象是一个List、ArrayList、LinkedList还是其它什么东西,2、迭代器的声明publicinterfaceIterator注意:迭代器同样使用泛型,六、迭代器,3、迭代器的3个方法更详细资料请参阅官方文档,六、迭代器,booleanhasNext()Returnstrueiftheiterationhasmoreelements检查序列中是否还有元素Enext()Returnsthenextelementintheiteration获取序列中的下一个元素,迭代器的工作方式:游标+单向移动只要hasNext方法返回true就可以利用next方法,将迭代器的光标移动到下一个元素,并且返回对前元素的引用,如果反复调用next方法即可从头至尾遍历线性表或者整个容器一旦next方法已经返回了集合中的最后一个元素,再继续调用next方法将抛出一个异常抛出的异常名字叫NoSunckElementException,voidremove()将迭代器最新返回的元素删除也就是说:在调用remove方法之前,必须调用了next方法,然后再删除由next方法返回的元素,4、迭代器的应用典例迭代器的典型使用方式:while循环不要看书上的例子(涉及到后面内容),六、迭代器,/创建一个ArrayList对象,并返回指向该对象的引用,然后向上转型为指向List接口的引用Listlist1=newArrayList();/向容器list1中添加元素list1.Add(“a”);list1.Add(“b”);list1.Add(“c”);,/定义一个迭代器/迭代器的初始位置在集合的第一个元素之前Iteratoriter=list1.iterator();while(iter.hasNext()Stringstr=(String)iter.next();System.out.println(str);,5、ListIteratorListIterator是一种功能上更加强大的Iterator的子类型它用于各种实现List接口的类的访问,六、迭代器,ListIterator迭代器允许双向遍历线性表并且在遍历过程中可以修改线性表除了Iterator接口所说明的3个方法hasNext、next和remove之外ListIterator还含有诸如hasPrevious、previous、add和set等等方法,1、栈(Stack)的概念栈是一种后进先出(LIFO)的容器,七、Stack,2、LinkedList具有能够直接实现栈的所有功能的方法因此可以直接将LinkedList当成栈使用,七、Stack,但是如果你只需要的是栈的方法,这里使用继承就不合适了原因在于:这样将会产生具有LinkedList的其它所有方法的类Java1.0的设计者在创建java.util.Stack时就犯了这个错误(所设计的Stack继承自Vector),3、我们试图创建一个全新的栈利用LinkedList+泛型,七、Stack,importjava.util.LinkedList;publicclassStackprivateLinkedListstorage=newLinkedList();/storage是指向LinkedList类对象的一个引用/而LinkedList容器用来存放泛型T的对象,publicvoidpush(Tv)storage.addFirst(v);publicTpop()returnstorage.removeFirst();publicTpeek()/类似于getTopreturnstorage.getFirst();,publicbooleanempty()returnstorage.isEmpty();publicStringtoString()returnstorage.toString();,类名之后的告诉编译器这是一个参数化类型,也就是泛型,而其中的类型参数,在类被使用时将会被具体类型所替换这样,我们可以将classStack解释为:定义一个可以持有T类型对象的StackStack是用LinkedList实现的,而后者也将被告知它将持有T类型对象,注意这个类的使用方式需要完整的指出包含所创建的这个类的包名,或者更改这个类的名词否则,就可能与java.util中的Stack发生冲突,1、Set的概念Set是一种不保存重复元素的Collection实际上,Set具有与Collection完全一样的接口,只是行为不同(而这正是多态的典型应用),八、Set接口的总结,2、TreeSet、HashSet和LinkedHashSet这三种类中的元素具有不同的存储方式,因而在处理和输出等环节,我们所看到的效果并不一致,八、Set接口的总结,TreeSet将元素存储于红黑树的数据结构中HashSet使用散列函数LinkedHashSet使用链表来维护元素的插入顺序,八、Set接口的总结,publicclassSortedSetOfIntegerpublicstaticvoidmain(Stringargs)Randomrand=newRandom(47);SortedSetintset=newTreeSet();/向上转型为实现其父接口的类的对象,for(inti=0;i10000;i+)intset.add(rand.nextInt(30);System.out.println(intset);注意:虽然add了10000个数据,但是在intset容器中只包含有30个,而且还是有序的,将对象映射到其它对象的能力是一种解决问题的杀手锏典例:考虑一个程序,它将用来检查Java的Random类的随机性,九、Map接口的总结,解题思路:理想状态下,Random将会产生理想的数字分布,但如果我们想要测试这个结论,需要生成大量的随机数,并对落入不同范围的数字进行计数然而如果利用Map却容易解决该问题,在本例中:键是由Random产生的数字值是该数字出现的次数,importjava.util.*;publicclassStatisticspublicstaticvoidmain(Stringargs)/产生一个随机数的种子Randomrand=newRandom(47);,Mapm=newHashMap();for(inti=0;i10000;i+)/产生一个0到20之间的随机数intr=rand.nextInt(20);,Integerfreq=m.get(r);自动包装机制将随机生成的int转换为HashMap可以使用的Integer引用如果键不在容器中,get方法将返回null,表示该数字第一次被找到;否则,get方法将返回与该键相关联的Integer值(表示该数字出现的次数),m.put(r,freq=null?1:freq+1);自动包装机制将再次简化了表达式,这里使用的是对Integer的拆包将键值对放入容器中/最后,输出结果System.out.println(m);,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论