《Java SE程序设计及实践》课件07-第7章 泛型与集合_第1页
《Java SE程序设计及实践》课件07-第7章 泛型与集合_第2页
《Java SE程序设计及实践》课件07-第7章 泛型与集合_第3页
《Java SE程序设计及实践》课件07-第7章 泛型与集合_第4页
《Java SE程序设计及实践》课件07-第7章 泛型与集合_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

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

文档简介

-1-理解泛型的概念掌握泛型类的创建和使用理解泛型的有界类型和通配符的使用了解泛型的局限性理解Java集合框架的结构掌握Java迭代器接口的使用掌握List、Set、Map等结构集合类的使用掌握foreach语句的使用目标-2-泛型概述什么是泛型 泛型是JDK5.0的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数。这种类型参数可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

Java语言引入泛型的目的主要是为了类型安全。 在JDK5.0之前,没有泛型的情况的下,使用Object类型的变量来代表任意类型的数据,但“任意化”带来的缺点是需要显式的强制类型转换,此种转换要求开发者必须明确知道变量的真实类型。对于强制类型转换错误的情况,编译器可能不提示错误,但在运行的时候会出现异常,这是一个安全隐患。-3-泛型概述-1不使用泛型实现参数化类型publicclassNoGeneric{ privateObjectob;//定义一个通用类型成员

publicNoGeneric(Objectob){ this.ob=ob; } publicObjectgetOb(){ returnob; } publicvoidsetOb(Objectob){ this.ob=ob; } publicvoidshowType(){ System.out.println("实际类型是:"+ob.getClass().getName()); }}-4-泛型概述-2再创建一个Integer版本和String版本的NoGeneric对象进行测试,代码如下:publicclassNoGenericDemo{ publicstaticvoidmain(String[]args){ //定义类NoGeneric的一个Integer版本

NoGenericintOb=newNoGeneric(newInteger(88)); intOb.showType(); inti=(Integer)intOb.getOb(); System.out.println("value="+i); //定义类NoGeneric的一个String版本

System.out.println("----------------------------------"); NoGenericstrOb=newNoGeneric("HelloGen!“); strOb.showType(); Strings=(String)strOb.getOb(); System.out.println("value="+s); }}执行结果如下:实际类型是:java.lang.Integervalue=88---------------------------------实际类型是:java.lang.Stringvalue=HelloGen!-5-泛型概述-3使用泛型实现参数化类型 首先利用泛型定义泛型类Generic,代码如下:

publicclassGeneric<T>{privateTob;//定义泛型成员变量

publicGeneric(Tob){ this.ob=ob;}publicTgetOb(){ returnob;}publicvoidsetOb(Tob){ this.ob=ob;}publicvoidshowTyep(){ System.out.println("实际类型是:"+ob.getClass().getName());}}-6-泛型概述-4再创建一个Integer版本和String版本的Generic对象进行测试,代码如下:publicclassGenericDemo{ publicstaticvoidmain(String[]args){ //定义泛型类Genneric的一个Integer版本

Generic<Integer>intOb=newGeneric<Integer>(88); intOb.showTyep();

inti=intOb.getOb(); System.out.println("value="+i); System.out.println("----------------------------------"); //定义泛型类Genneric的一个String版本

Generic<String>strOb=newGeneric<String>("HelloGen!"); strOb.showTyep();

Strings=strOb.getOb(); System.out.println("value="+s); }}执行结果如下:实际类型是:java.lang.Integervalue=88----------------------------------实际类型是:java.lang.Stringvalue=HelloGen!-7-泛型定义泛型语法结构归纳为如下形式:classclass-name<type-param-list>{//…}实例化泛型类的语法结构如下:class-name<type-param-list>obj =newclass-name<type-param-list>(cons-arg-list)用于指明当前泛型类可接受的类型参数占位符的个数-8-有界类型-1有界类型

定义泛型类时,可以向类型参数指定任何类型信息,特别是集合框架操作中,可以最大限度的提高泛型类的适用范围。但有时候需要对类型参数的取值进行一定程度的限制,以使数据具有可操作性。

为了处理这种情况,Java提供了有界类型。在指定类型参数时可以使用extends关键字限制此类型参数代表的类必须继承自指定父类或父类本身。-9-有界类型-2有界类型实例publicclassBoundGeneric<TextendsNumber>{ //定义泛型数组

T[]array; publicBoundGeneric(T[]array){ this.array=array; } //计算总和

publicdoublesum(){ doublesum=0.0; for(Telement:array){ sum=sum+element.doubleValue(); } returnsum; }}-10-有界类型-3测试BoundGeneric类publicclassBoundGenericDemo{publicstaticvoidmain(String[]args){ Integer[]intArray={1,2,3,4}; //使用整型数组构造泛型对象

BoundGeneric<Integer>iobj=newBoundGeneric<Integer>(intArray); System.out.println("iobj的和为:"+iobj.sum()); Double[]dArray={1.0,2.0,3.0,4.0}; //使用Double型数组构造泛型对象

BoundGeneric<Double>dobj=newBoundGeneric<Double>(dArray); System.out.println("dobj的和为:"+dobj.sum()); String[]strArray={"str1","str2"}; //下面语句将报错,String不是Number的子类

//BoundGeneric<String>sobj=newBoundGeneric<String>(strArray);}}前两个输出执行结果如下:iobj的和为:10.0dobj的和为:10.0-11-泛型的局限性Java并没有真正实现泛型,是编译器在编译的时候在字节码上做了手脚(称为擦除),是编译器级别的,虚拟机并不知道有没有泛型。这样做的主要原因是为了兼容Java的早期版本。但是这种实现理念造成Java的泛型存在一些问题。为了规避这些问题Java对泛型的使用上做了一些约束,但不可避免的还是有一些问题存在。这其中大多数限制都是由类型擦除引起的。泛型类型不能被实例化不能声明参数化类型的数组不能用类型参数替换基本类型不能定义带泛型的异常。不允许定义Throwable的泛型子类。不能在静态变量或者静态方法中引用类中声明的类型参数。

-12-集合概述-1集合框架

Java中对常用的数据结构和算法做了一些规范和实现。所有抽象出来的数据结构和操作统称为Java集合框架(JavaCollectionFramework,简称JCF)。集合框架的引入给编程操作带来了如下的优势:集合框架强调了软件的复用。集合框架通过提供有用的数据结构和算法,使开发者能集中注意力于程序的重要部分上集合框架通过提供对有用的数据结构(动态数组、链接表、树和散列表等)和算法的高性能、高质量的实现使程序的运行速度和质量得到提高集合框架必须允许不同类型的数据以相同的方式和高度互操作方式工作集合框架允许扩展或修改集合框架API易学易用集合框架主要由一组用来操作对象的接口组成,不同接口描述一组不同数据类型-13-集合概述-2Java的集合框架主要由一组用来操作对象的接口组成,不同接口描述一组不同数据类型。抽其核心,主要接口有:Collection、List、Set和Map。简化框架图如下所示:-14-Collection接口Collection接口

Collection接口是构造集合框架的基础,用于表示任何对象的集合。该接口中声明了所有集合都拥有的核心方法,例如基本的添加、删除操作等,并且提供了一组操作成批对象的方法,还提供了支持查询操作如判断集合是否为空的方法等。Collection在使用时需要注意以下事项:

其中几种方法可能会引发一个UnsupportedOperationException异常当企图将一个不兼容的对象加入一个类集中时,将产生ClassCastException异常Collection并没有get()方法来随机访问第几个元素。只能通过iterator()遍历元素-15-List接口List接口

List是最常用的一种集合。List接口继承了Collection接口,元素允许重复,以元素添加的次序来放置元素,不会重新排列。该接口不但能够对列表的一部分进行处理,还允许针对位置索引的随机操作。它的具体实现类常用的有ArrayList和LinkedList。List在使用时需要注意以下事项:

如果集合不可更改,其中几个方法将引发一个UnsupportedOperationException异常当企图将一个不兼容的对象加入一个类集中时,将产生ClassCastException异常如果使用无效索引,一些方法将出IndexOutOfBoundsException异常-16-Set接口和Map接口Set接口

Set接口继承Collection接口,Set中的对象元素不能重复,其元素添加后采用自己内部的一个排列机制。Set接口没有引入新方法,可以说Set就是一个Collection,只是行为不同。它的常用具体实现有HashSet和TreeSet类。Map接口

Map接口没有继承Collection接口。Map接口是用于维护键/值对(key/value)的集合,Map容器中的键不允许重复,而值可以是任意对象。Map有两种比较常用的实现:HashMap和TreeMap。

-17-Collections类和Arrays类Collections和Arrays

集合框架中还有两个很实用的辅助类:Collections和Arrays。Collections提供了对一个Collection类型的容器进行诸如排序、复制、查找和填充等一些非常有用的方法;Arrays则提供了针对数组进行类似操作的方法。

-18-迭代器Iterator接口

为了支持对Collection进行一致的遍历操作,Java的集合框架提供了Iterator接口,使用者可以采用一致的方式操作Collection,而不需知道这个Collection的具体实现类型。Iterator接口中的方法能以迭代方式逐个访问集合中各个元素,并安全的从Collection中删除元素。ListIterator接口

ListIterator接口继承Iterator接口,是列表迭代器,用以支持添加或更改底层集合中的元素,允许程序员双向访问、修改列表。ListIterator没有当前位置,光标位于调用previous和next方法返回的值之间,是一个长度为n的列表,有n+1个有效索引值。

-19-ListArrayList

ArrayList支持可随需要而调整的动态数组。其内部封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个capacity。这个capacity表示存储列表中元素的数组的容量。当元素添加到ArrayList时,它的capacity可根据需要的容量自动增加。在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity()方法增加capacity,此方法可以减少重分配的次数。LinkedList

LinkedList类提供了一个链表数据结构,更适合频繁的数据增删操作。-20-List-1for-each

JDK5.0提供了一种全新的for循环——for-each形式,for-each可以遍历实现Iterable接口的任何对象的集合,其操作形式比迭代器更方便有效。

for-each遍历实例publicclassArrayListDemo{ //......省略代码部分

//使用for-each遍历

publicstaticvoidtravel2(){

for(Stringstr:arrayList){ System.out.println(str); } } //......省略代码部分}-21-SetHashSet

HashSet能快速定位一个元素。该结构使用散列表进行存储。

publicclassHashSetDemo{ publicstaticvoidmain(Stringargs[]){

HashSet<String>hashSet=newHashSet<String>(); //添加元素

hashSet.add("first"); hashSet.add("second"); hashSet.add("third"); hashSet.add("forth"); System.out.println(hashSet); //遍历

for(Stringstr:hashSet){ System.out.println(str); } }}执行结果如下:[forth,second,third,first]forthsecondthirdfirst-22-Set-2TreeSet

TreeSet是使用树结构来进行存储,并且能够保证元素已排序。存储大量的需要进行快速检索的排序信息的情况下,TreeSet是一个很好的选择。TreeSet实例演示publicclassTreeSetDemo{ publicstaticvoidmain(Stringargs[]){ TreeSet<String>treeSet=newTreeSet<String>(); //添加元素

treeSet.add("first"); treeSet.add("second"); treeSet.add("third"); treeSet.add("forth"); System.out.println(treeSet); //遍历

for(Stringstr:treeSet){ System.out.println(str); } }}执行结果如下:[first,forth,second,third]firstforthsecondthird-23-MapMap Map是一种把键对象和值对象关联的容器,Map中的键不允许重复。

Map中提供了Map.Entry接口,通过Map的entrySet方法返回一个实现Map.Entry接口的对象集合,使得可以单独操作Map的项(键/值对),在Map中的每一个项,就是一个Map.Entry对象,通过遍历每一个Entry,可以获得每一个条目的键或值并对值进行更改

温馨提示

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

评论

0/150

提交评论