1、第六章第六章 JAVA JAVA集合、泛型和枚举集合、泛型和枚举本章学习要点本章学习要点了解集合概念及结构;掌握Arraylist集合的使用方法;掌握LinkedList集合的使用方法;掌握Set集合的使用方法;掌握HashSet集合的使用方法;掌握TreeSet集合的使用方法;掌握HashMap集合的使用方法;掌握TreeMap集合的使用方法;掌握Iterator的使用方法;了解泛型集合的概念及使用方法。6.1 JAVA 6.1 JAVA集合类的概念集合类的概念 6.1.1 6.1.1 集合中的接口集合中的接口 6.1.2 6.1.2 接口实现类接口实现类 6.1.1 6.1.1 集合中的接
2、口集合中的接口 集合框架是一个类库的集合,包含实现集合的接口。接口是集合的抽象数据类型,提供对集合中所表示的内容进行单独操作的可能。常见的集合接口有四种。Collection:该接口是最基本的集合接口,存储不唯一的无序的数据。List:该接口实现了Collection接口,存储有序的不唯一的数据。Set:该接口实现了Collection接口,存储无序的唯一的数据。Map:以健值对的形式存储数据,以键取值,键不能重复,值可以重复。6.1.1 6.1.1 集合中的接口集合中的接口 集合框架中的接口结构如图所示。6.1.2 6.1.2 接口实现类接口实现类 List接口的常用实现类有ArrayLis
3、t、LinkedList和Vector。Set接口常用的实现类有HashSet和TreeSet。Map接口的常用实现类有HashMap和TreeMap。集合框架接口中实现类的结构如图所示。6.2 JAVA COLLECTION接口 Collection是最基本的集合接口,声明了适用于Java集合(只包括Set和List)的通用方法。Map接口并不是Collection接口的子接口,但是它仍然被看作是Collection框架的一部分。6.2 JAVA COLLECTION接口 Collection接口中常用的方法如下:方法名称方法名称说明说明boolean add(E e)boolean add
4、(E e)向集合中添加一个元素,E是元素的数据类型boolean addAll(Collection c)boolean addAll(Collection c)向集合中添加集合c中的所有元素void clear()void clear()删除集合中的所有元素boolean contains(Object o)boolean contains(Object o)判断集合中是否存在指定元素boolean containsAll(Collection c)boolean containsAll(Collection c)判断集合中是否包含集合c中的所有元素boolean isEmpty()bool
5、ean isEmpty()判断集合是否为空Iteratoriterator()Iteratoriterator()返回一个Iterator对象,用于遍历集合中的元素boolean remove(Object o)boolean remove(Object o)从集合中删除一个指定元素boolean boolean removeAllremoveAll(Collection c)(Collection c)从集合中删除所有在集合c中出现的元素boolean retainAll(Collection c)boolean retainAll(Collection c)仅仅保留集合中所有在集合c中出现
6、的元素int size()int size()返回集合中元素的个数Object toArray()Object toArray()返回包含此集合中所有元素的数组 6.3 JAVA LIST 6.3 JAVA LIST集合集合 6.3.1 6.3.1 ArrayListArrayList类类 6.3.2 6.3.2 LinkListLinkList类类6.3.1 6.3.1 ARRAYLISTARRAYLIST类类 List接口实现了Collection接口,它主要有两个实现类:ArrayList类和LinkedList类。在List集合中允许出现重复元素。与Set集合不同的是,在List集合中
7、的元素是有序的,可以根据索引位置来检索List集合中的元素,第一个添加到List集合中的元素的索引为0,第二个为1,依此类推。6.3.1 6.3.1 ARRAYLISTARRAYLIST类类 ArrayList是Java集合框架中的一个重要的类,它继承于AbstractList,实现了List接口,是一个长度可变的集合,提供了增删改查的功能。集合中允许null的存在。ArrayList类还是实现了RandomAccess接口,可以对元素进行快速访问。实现了Serializable接口,说明ArrayList可以被序列化,还有Cloneable接口,可以被复制。和Vector不同的是,Array
8、List不是线程安全的。6.3.1 6.3.1 ARRAYLISTARRAYLIST类类 构造方法如下:构造方法构造方法说明说明ArrayListArrayList()()默认提供初始容量为10的空列表。ArrayList(int initialCapacity)ArrayList(int initialCapacity)构造一个具有指定初始容量的空列表。ArrayList(Collectionc)ArrayList(Collectionc)构造一个包含指定collection的元素6.3.1 6.3.1 ARRAYLISTARRAYLIST类类 常用方法:方法名称方法名称说明说明E get(
9、int index)E get(int index)获取此集合中指定索引位置的元素,E 为集合中元素的数据类型int index(Object o)int index(Object o)返回此集合中第一次出现指定元素的索引,如果此集合不包含该元素,则返回-1int lastIndexOf(Obj ect o)int lastIndexOf(Obj ect o)返回此集合中最后一次出现指定元素的索引,如果此集合不包含该元素,则返回-1E set(int index,E element)E set(int index,E element)将此集合中指定索引位置的元素修改为 element 参数指定
10、的对象。此方法返回此集合中指定索引位置的原元素List subList(int fromlndex,int tolndex)List subList(int fromlndex,int tolndex)返回一个新的集合,新集合中包含 fromlndex 和 tolndex 索引之间的所有元素。包含 fromlndex 处的元素,不包含 tolndex 索引处的元素6.3.2 6.3.2 LINKLISTLINKLIST类类 ArrayList基于动态数组的实现,它长于随机访问元素,但是在中间插入和移除元素时较慢。LinkedList基于链表实现,在List中间进行插入和删除的代价较低,提供了优
11、化的顺序访问。LinkedList在随机访问方面相对比较慢,但是它的特性集较ArrayList更大。6.3.2 6.3.2 LINKLISTLINKLIST类类 常用方法方法名称方法名称说明说明void addFirst(E e)void addFirst(E e)将指定元素添加到此集合的开头void addLast(E e)void addLast(E e)将指定元素添加到此集合的末尾E getFirst()E getFirst()返回此集合的第一个元素E E getLastgetLast()()返回此集合的最后一个元素E removeFirst()E removeFirst()删除此集合中
12、的第一个元素E removeLast()E removeLast()删除此集合中的最后一个元素 6.4 JAVA SET 6.4 JAVA SET集合集合 6.4.1 HashSet 6.4.1 HashSet 类类 6.4.2 6.4.2 TreeSetTreeSet 类类 6.4.1 HASHSET 6.4.1 HASHSET 类类 Set集合也实现了Collection接口,它主要有两个实现类:HashSet类和TreeSet类。Set集合中的对象不按特定的方式排序,只是简单地把对象加入集合,集合中不能包含重复的对象,并且最多只允许包含一个null元素。HashSet查找某个对象时,首先
13、用hashCode()方法计算出这个对象的Hash码,然后再根据Hash码到相应的存储区域用equals()方法查找,从而提高了效率。由于是集合,所以同一个对象只能有一个。6.4.1 HASHSET 6.4.1 HASHSET 类类 常用方法方法名称方法名称说明说明boolean boolean addadd(E E e)e)将指定的元素添加到此集合(如果尚未存在)void void clearclear()()从此集合中删除所有元素boolean boolean containscontains(ObjectObject o)o)如果此集合包含指定元素,则返回trueboolean bool
14、ean isEmptyisEmpty()()如果此集合不包含元素,则返回trueIteratorIterator iteratoriterator()()返回此集合中元素的迭代器boolean boolean removeremove(ObjectObject o)o)如果存在则从该集合中删除指定的元素int int sizesize()()返回此集合中的元素数(其基数)SpliteratorSpliterator spliteratorspliterator()()在此集合中的元素上创建late-binding和故障快速Spliterator 6.4.2 6.4.2 TREESETTREES
15、ET 类类 TreeSet类同时实现了Set接口和SortedSet接口。SortedSet接口是Set接口的子接口,可以实现对集合进行自然排序,因此使用TreeSet类实现的Set接口默认情况下是自然排序的,这里的自然排序指的是升序排序。6.4.2 6.4.2 TREESETTREESET 类类 构造方法:方法方法说明说明TreeSet()TreeSet()构造一个新的,空的树组,根据其元素的自然排序进行排序TreeSet(Collection c)TreeSet(Collection c)构造一个包含指定集合中的元素的新树集,根据其元素的自然排序进行排序TreeSetTreeSet(Com
16、parator comparator)(Comparator comparator)构造一个新的,空的树集,根据指定的比较器进行排序TreeSet(SortedSet s)TreeSet(SortedSet s)构造一个包含相同元素的新树,并使用与指定排序集相同的顺序 6.4.2 6.4.2 TREESETTREESET 类类 常用方法:方法名称方法名称说明说明boolean boolean addadd(E E e)e)将指定元素添加到此集合Boolean Boolean addAlladdAll(CollectionCollection?extends c)c)将指定集合中的所有元素添加到
17、此集合E E ceilingceiling(E E e)e)返回此集合中最小元素大于或等于给定元素,如果没有此元素,则返回nullVoid Void clearclear()()从此集合中删除所有元素ComparatorComparator?super comparatorcomparator()()返回用于对该集合中的元素进行排序的比较器,或null,如果此集合使用其元素的natural orderingboolean boolean containscontains(ObjectObject o)o)如果此集合包含指定的元素,则返回trueIteratorIterator descendi
18、ngIteratordescendingIterator()()以降序返回该集合中的元素的迭代器。6.5 JAVA MAP 6.5 JAVA MAP 集合集合 6.5.1 HashMap6.5.1 HashMap类类 6.5.2 6.5.2 TreeMapTreeMap类类6.5.1 HASHMAP6.5.1 HASHMAP类类 Map是一种键-值对(key-value)集合,Map集合中的每一个元素都包含一个键对象和一个值对象。其中,键对象不允许重复,而值对象可以重复,并且值对象还可以是Map类型的,就像数组中的元素还可以是数组一样。Map接口主要有两个实现类:HashMap 类和TreeM
19、ap类。其中,HashMap类按哈希算法来存取键对象,而TreeMap类可以对键对象进行排序。6.5.1 HASHMAP6.5.1 HASHMAP类类 HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。构造方法:方法方法说明说明HashMap()HashMap()构造一个空的HashMap,默认初始容量(16)和默认负载系数(0.75)HashMap(int initialCapacity)HashMap(int initialCapacity)构造一个空的HashMap具有指定的初始容量和默认负载因子(0.75)HashM
20、ap(int HashMap(int initialCapacityinitialCapacity,float,float loadFactorloadFactor)构造一个空的HashMap具有指定的初始容量和负载因子HashMap(Map m)HashMap(Map m)构造一个新的HashMap与指定的相同的映射Map6.5.1 HASHMAP6.5.1 HASHMAP类类 常用方法方法名称方法名称说明说明void void clearclear()()从这张地图中删除所有的映射boolean boolean containsKeycontainsKey(ObjectObject key
21、)key)如果此映射包含指定键的映射,则返回trueBoolean Boolean contains Valuecontains Value(ObjectObject value)value)如果此地图将一个或多个键映射到指定值,则返回trueSetSet Map.EntryMap.Entry entrySetentrySet()()返回此地图中包含的映射的Set视图V V getget(ObjectObject key)key)返回到指定键所映射的值,或null如果此映射包含该键的映射Boolean Boolean isEmptyisEmpty()()如果此地图不包含键值映射,则返回true
22、SetSet keySetkeySet()()返回此地图中包含的键的Set视图V V putput(K K key,key,V V value)value)将指定的值与此映射中的指定键相关联V V removeremove(ObjectObject key)key)从该地图中删除指定键的映射(如果存在)Int Int sizesize()()返回此地图中键值映射的数量6.5.2 6.5.2 TREEMAPTREEMAP类类 TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator进行排序,具体取决于使用的构造
23、方法。构造方法:方法名称方法名称说明说明TreeMap()TreeMap()使用其键的自然排序构造一个新的空树状图TreeMap(Comparator comparator)TreeMap(Comparator comparator)构造一个新的,空的树图,按照给定的比较器排序TreeMapTreeMap(Map m)(Map m)构造一个新的树状图,其中包含与给定地图相同的映射,根据其键的 自然顺序进行排序TreeMap(SortedMap m)TreeMap(SortedMap m)构造一个包含相同映射并使用与指定排序映射相同顺序的新树映射6.5.2 6.5.2 TREEMAPTREEMA
24、P类类 常用方法:方法名称方法名称说明说明void void clearclear()()从这张地图中删除所有的映射boolean boolean containsKeycontainsKey(ObjectObject key)key)如果此地图将一个或多个键映射到指定值,则返回trueSetSet Map.EntryMap.Entry entrySetentrySet()()返回此地图中包含的映射的Set视图V V getget(ObjectObject key)key)返回到指定键所映射的值,或null如果此映射包含该键的映射SetSet keySetkeySet()()返回此地图中包含的
25、键的Set视图V V putput(K K key,key,V V value)value)将指定的值与此映射中的指定键相关联V V removeremove(ObjectObject key)key)从此TreeMap中删除此键的映射(如果存在)int size()int size()返回此地图中键值映射的数量 6.6 6.6 泛型集合泛型集合 6.6.1 6.6.1 泛型的概念泛型的概念 6.6.2 6.6.2 泛型类泛型类 6.6.3 6.6.3 泛型接口泛型接口 6.6.4 6.6.4 泛型方法泛型方法 6.6.1 6.6.1 泛型的概念泛型的概念 泛型(Generic type或者g
26、enerics)是对Java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。例如,Map类允许您向一个Map添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如String)的对象。因为Map.get()被定义为返回Object,所以一般必须将Map.get()的结果强制类型转换为期望的类型,如下面的代码所示:Map m=new HashMap();m.put(key,blarg);String s=(String)m.get(key);6.6.
27、1 6.6.1 泛型的概念泛型的概念 理想情况下,您可能会得出这样一个观点,即m是一个Map,它将String键映射到String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。消除强制类型转换。泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法6.6.2 6.6.2 泛型类泛型类 泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:Li
28、st、Set、Map。泛型类的最基本写法。public class class_name 可以定义一个或多个泛型类型,例如。class GenericA 或者class GenericA6.6.3 6.6.3 泛型接口泛型接口 泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,可以看一个例子:定义一个泛型接口 public interface Generator public T next();6.6.3 6.6.3 泛型接口泛型接口 当实现泛型接口的类,未传入泛型实参时:class FruitGenerator implements Generator Override
29、 public T next()return null;6.6.3 6.6.3 泛型接口泛型接口 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中,即:class FruitGenerator implements Generator 如果不声明泛型,如:class FruitGenerator implements Generator 编译器会报错:Unknown class6.6.3 6.6.3 泛型接口泛型接口 当实现泛型接口的类,传入泛型实参时:public class FruitGenerator implements Generator priva
30、te String fruits=new StringApple,Banana,Pear;Override public String next()Random rand=new Random();return fruitsrand.nextInt(3);6.6.3 6.6.3 泛型接口泛型接口 传入泛型实参时:定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator。但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型,即:Generator,public T
31、 next();中的的T都要替换成传入的String类型。6.6.4 6.6.4 泛型方法泛型方法 到目前为止,我们所使用的泛型都是应用于整个类上。泛型同样可以在类中包含参数化的方法,而方法所在的类可以是泛型类,也可以不是泛型类。也就是说,是否拥有泛型方法,与其所在的类是不是泛型没有关系。泛型方法使得该方法能够独立于类而产生变化。如果使用泛型方法可以取代类泛型化,那么就应该只使用泛型方法。另外,对一个static的方法而言,无法访问泛型类的类型参数。因此,如果static方法需要使用泛型能力,就必须使其成为泛型方法。6.7 JAVA JAVA图书信息查询图书信息查询 前面详细介绍了Java中各
32、集合的使用,像Set集合和List集合等,另外,还结合泛型讲解了一些高级应用。在实际开发中,泛型集合是较常用的,一般定义集合都会使用泛型的形式来定义。本节将使用泛型集合来模拟实现某图书管理系统的查询功能。在图书管理系统中为了方便管理图书,将图书划分为几个类别。每个类别下有很多图书,每本图书都有相对应的类别,这就具备了一对多的关系映射,即一个类别对应多本图书。在这种情况下就可以使用Map映射来存储类别和图书信息,其键为Category(类别)类型,值为List类型(Book类为图书类),然后使用嵌套循环遍历输出每个类别所对应的多个图书信息。6.86.8本章小结本章小结 本章主要介绍了各种集合之间的关系及各自的特点,介绍了List集合的两种实现类ArrayList和LinkedList,介绍了Set集合的两种实现类HashSet和TreeSet,介绍了Map集合的两种实现类HashMap和TreeMap。介绍了泛型的概念,泛型类、泛型接口和泛型方法。