1、Java集合集合Java集集合合类是是一一种种特特别有有用用的的工工具具类,可可用用于于存存储数数量量不不等等的的对象象,并并可可以以实现常常用用的的数数据据结构构,如如栈、队列列等等。除除此此之之外外java集集合合还可可用用于于保保存存具具有有映映射射关关系系的的关关联数数组。Java集集合合大大致致可可分分为Set、List、Queue和和Map四四种种体体系系,其其中中Set代代表表无无序序、不不可可重重复复的的集集合合;List代代表表有有序序、重重复复的的集集合合;而而Map则代代表表具具有有映映射射关关系系的的集集合合。Java5中中又又增增加加了了Queue体体系系集集合合,代
2、代表表一一种种队列集合列集合实现。第一第一节 Java集合概述集合概述p为了了保保存存数数量量不不确确定定的的数数据据,以以及及保保存存具具有有映映射射关关系系的的数数据据(也也称称为关关联素素组),Java提提供供了了集集合合类。集集合合类主主要要负责保保存存、盛盛装装其其他他数数据据,因因此此集集合合类也也被被称称为容容器器类。所所有有的的集集合合类都都位位于于java.util包包下下,后后来来为了了处理理多多线程程环境境下下的的并并发安安全全问题,java5还在在java.util.concurrent包包下下提提供供了了一一些些多多线程程支支持的集合持的集合类。p集集合合类和和数数组
3、不不一一样,数数组元元素素既既可可以以是是基基本本数数据据类型型,又又可可以以是是对象象(实际上上保保存存的的是是对象象的的引引用用变量);而集合只能保存量);而集合只能保存对象。象。pJava的的 集集 合合 类 主主 要要 由由 两两 个个 接接 口口 派派 生生 而而 出出:Collection和和Map。Collection接口及其接口及其派生派生类Map体系的继承树体系的继承树第二第二节 Collection和和Iteration接口接口Collection接接口口是是List、Set和和Queue接接口口的的父父接接口口,该接接口口里里定定义的的方方法法既既可可用用于于操操作作Se
4、t集集合合,也也可可用用于于操操作作List和和Queue集合。集合。Collection接口里定接口里定义了如下操作集合元素的方法。了如下操作集合元素的方法。pboolean add(Object o):用于向集合里添加一个元素,如果集合对象被添加操作改变了,则返回true。pboolean addAll(Collection c):该方法把集合c里的所有元素添加到指定集合里。如果集合对象被添加操作改变了,则返回true。pvoid clear():清除集合里所有元素,将集合长度变为0;pboolean contains(Object o):返回集合里是否包含指定元素。pboolean co
5、ntainsAll(Collection c):返回集合里是否包含集合c里所有元素。pboolean isEmpty():返回集合是否为空。当集合长度为0时返回true。否则返回false。pIterator iterator():返回一个Iterator对象,用于遍历集合里的元素。pboolean remove(Object o):从此 collection 中移除指定元素的单个实例,存在多个只删除第一个。pboolean removeAll(Collection c):移除此 collection 中那些也包含在指定 c中的所有元素,如果删除了一个或一个以上,则返回true。pboolea
6、n retainAll(Collection c):从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集),如果该操作改变了调用该方法的集合,则该方法返回true。pint size():该方法返回集合里元素的个数。pObject toArray():该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素。小练习:小练习:因为所有的因为所有的Collection实现类实现类都重写了都重写了toString()方法,该方方法,该方法可以一次性输出集合中所有法可以一次性输出集合中所有元素。元素。上上面面程程序序中中创建建了了两两个个Collection对象象,一
7、一个个是是c集集合合,一一个个是是books集集合合,其其中中c集集合合是是ArrayList,而而books集集合合是是HashSet。虽然然他他们使使用用的的实现类不不同同,但但 当当 把把 他他 们 当当 成成 Collection来来 使使 用用 时,使使 用用 add,remove,clear等方法完全没有任何区等方法完全没有任何区别。1.使用使用Lambda表达式遍表达式遍历集合集合java8为Iterable接接口口新新增增了了一一个个forEach(Consumer action)默默认方方法法,该方方法法所所需需参参数数的的类型型是是一一个个函函数数式式接接口口,而而Iter
8、able接接口口是是Collection接接口口的的父父接接口口,因此因此Collection集合也可以直接集合也可以直接调用用该方法。方法。当当程程序序调用用Iterable的的forEach(Consumer action)遍遍历集集合合元元素素时,程程序序会会依依次次将将集集合合元元素素传给Consumer的的accept(T,t)方方法法(该接接口口中中唯唯一一的的抽抽象象方方法法)。正正 因因 为 Consumer是是 函函 数数 式式 接接 口口,因因 此此 可可 以以 使使 用用Lambda表达式来遍表达式来遍历集合元素。集合元素。2.使用使用foreach循循环遍遍历集合元素集
9、合元素除除了了可可以以使使用用Iterator接接口口迭迭代代访问Collection集集合合里里的的元元素素之之外外,使使用用Java5提提供供的的foreach循循环迭迭代代访问集合元素更加便捷。集合元素更加便捷。Collection books=new HashSet();books.add(JavaEE);books.add(Android);/使用foreach循环来迭代访问Collection集合元素for(Object obj:books)String book=(String)obj;System.out.println(book);3.使用使用Java8新增的新增的Predi
10、cate操作集合操作集合Java8为Collection集集合合新新增增了了一一个个removeIf(Predicate filter)方方法法,该方方法法见鬼鬼批批量量删除除 符符 合合 filter条条 件件 的的 所所 有有 元元 素素。该 方方 法法 需需 要要 一一 个个Predicate(谓词)对象象作作为参参数数,Predicate也也是是函函数数式式接口,因此可是用接口,因此可是用Lambda表示式作表示式作为参数。参数。4.使用使用Java8新增的新增的Stream操作集合操作集合Java8还新新增增了了Stream、InStream、LongStream、DoubleStr
11、eam等等流流式式API,这些些API代代表表多多个个支支持持串串行行和和并并行行聚聚集集操操作作的的元元素素。Stream是是一一个个通通用用的的流流接接口口,而而IntStream、LongStream、DoubleStream则代代表元素表元素类型型为int、long、double的流。的流。Java8还为上上面面每每个个流流式式API提提供供了了对应的的Builder,例例如如Stream.Builder,IntStream.Builder,LongBuilder,DoubleStream.Builder,开开发者者可可以以通通过这些些Builder来来创建建对应的流。的流。独立使用独
12、立使用Stream的步的步骤如下:如下:使使用用Stream或或XXXStream的的builder()类方方法法创建建Stream对应的的Builder。重重复复调用用Builder的的add()方方法法向向该流流中中添添加加多多个个元素。元素。调用用Builder的的builder()方方法法获取取该流流中中添添加加多多个个元素。元素。调用用Stream的聚集方法。的聚集方法。实例:例:注意:注意:IntStream的聚集方法只能的聚集方法只能执行一次。行一次。Stream提提供供了了大大量量的的方方法法进行行聚聚集集操操作作,这些些方方法法既既可可以以是是“中中间的的”(intermed
13、iate),也也可可以以是是“末末端端的的”(terminal)。)。中中间方方法法:中中间操操作作允允许流流保保持持打打开开状状态,并并允允许直直接接调用用后后续方方法法。上上面面程程序序中中的的map()方方法法就就是是中中间方方法。中法。中间方法的返回方法的返回值是另外一个流。是另外一个流。末末端端方方法法:末末端端方方法法是是对流流的的最最终操操作作,当当对某某个个Stream执行行末末端端方方法法后后,该流流将将会会被被“消消耗耗”且且不不可可再用。上面程序的再用。上面程序的sum(),count(),average()等就是末端等就是末端流的方法流的方法还有如下两个特征:有如下两个
14、特征:有有状状态的的方方法法:这种种方方法法会会给流流增增加加一一些些新新的的属属性性,比比如如元元素素的的唯唯一一性性、元元素素的的最最大大数数量量、保保证元元素素以以排排序序的的方方式式被被处理理等等。有有状状态的的方方法法往往往往需需要要更更大大的性能开的性能开销。短短路路方方法法:短短路路方方法法可可以以尽尽早早结束束对流流的的操操作作,不不必必检查所有的元素。所有的元素。介介绍一下一下Stream常用的方法:常用的方法:pfilter(Predicate predicate):过滤Stream中中所所有有不不符符合合predicate的元素。的元素。pmapToXxx(ToXxxFu
15、nction mapper):使使用用ToXxxFunction对流中的元素流中的元素执行一行一对一的一的转换。ppeek(Consumer action):依依次次对每每个个元元素素执行行一一些些操操作作,该方方法法返返回回的的流流与与原原有有流流包包含含相相同同的的元元素素。该方法主要用于方法主要用于调试。pdistinct():该方方法法用用于于排排序序流流中中所所有有重重复复的的元元素素(判判断断元元素素重重复复的的标准准是是使使用用equals()比比较返返回回true)。)。这是一个有状是一个有状态的方法。的方法。psorted():该方方法法用用于于保保证流流中中的的元元素素在在
16、后后续的的访问中中处于有序状于有序状态。这是一个有状是一个有状态的方法。的方法。plimit(long maxSize):该方方法法用用于于保保证对该流流的的后后续访问中中最最大大允允许访问的的元元素素个个数数。这是是一一个个有有状状态的、短路的方法。的、短路的方法。Stream常用的末端方法常用的末端方法pforEach(Consumer action):遍遍历流流中中所所有有元元素素,对每个元素每个元素执行行action。ptoArray():将流中所有元素将流中所有元素转换为一个数一个数组。preduce():该方方法法有有三三个个重重载的的版版本本,都都用用于于通通过某某种操作来合并流
17、中的元素。种操作来合并流中的元素。pmin():返回流中所有元素的最小:返回流中所有元素的最小值。pmax():返回流中所有元素的最大:返回流中所有元素的最大值。pcount():返回流中所有元素的数量。返回流中所有元素的数量。panyMatch(Predicate predicate):判判断断流流中中是是否否至至少包含一个元素符号符合少包含一个元素符号符合Predicate条件。条件。pallMatch(Prediacate predicate):判判断断流流中中是是否否每每个个元素都符合元素都符合Predicate条件。条件。pnoneMatch(Predicate predicate)
18、:判判断断流流中中是是否否所所有元素都不符合有元素都不符合Predicate条件。条件。pfindFirst():返回流中的第一个元素。返回流中的第一个元素。pfindAny():返回流中的任意一个元素。返回流中的任意一个元素。除除此此之之外外,Java 8 允允许使使用用流流式式API来来操操作作集集合合,Collection接接口口提提供供了了一一个个Stream()默默认方方法法,该方方法法可可返返回回该集集合合对应的的流流,接接下下来来计科科通通过流流式式API来来操操作作集集合合元元素素。由由于于Stream可可以以对集集合合元元素素进行行整整体体的的聚集操作,因此聚集操作,因此St
19、ream极极大地丰富了集合的功能。大地丰富了集合的功能。实例:例:第三第三节 Set集合集合set集集合合类似似一一个个罐罐子子,程程序序可可以以一一次次把把对象象丢进set集集合合,而而set集集合合通通常常不不能能记住住元元素素的的添添加加顺序序。Set集集合合与与Collection基基本本相相同同,没没有有提提供供任任何何额外外的的方方法法。实际上上Set就是就是Collection,只是行,只是行为略有不同。略有不同。set集集合合不不允允许包包含含相相同同元元素素,如如果果试图把把两两个个相相同同的的元元素素加加入入同同一一个个Set集集合合中中,则添添加加操操作作失失败,add(
20、)方方法返回法返回false,且新元素不会被加入。,且新元素不会被加入。上上面面介介绍的的是是set集集合合的的通通用用知知识,因因此此完完全全适适合合后后面面介介绍的的HashSet、TreeSet和和EnumSet三三个个实现类。只只是三个是三个实现类还各有特色。各有特色。1.HashSet类HashSet是是set接接口口的的典典型型实现,大大多多数数时候候使使用用Set集集合合时就就是是使使用用这个个实现类。HashSet按按Hash算算法法来来存存储集合中的元素,因此据很好的存集合中的元素,因此据很好的存储和和查找性能。找性能。HashSet具有以下特点:具有以下特点:p不不能能保保
21、证元元素素的的排排列列顺序序,顺序序可可能能与与添添加加顺序序不不同同,顺序也有可能序也有可能发生生变化。化。pHashSet不不是是同同步步的的,如如果果多多个个线程程同同时访问一一个个HashSet,假假设有有两两个个或或者者两两个个以以上上线程程同同时修修改改了了HashSet集合集合时,必,必须通通过代代码来保来保证其同步。其同步。p集合元素集合元素值可以是可以是null。当当向向HashSet集集合合中中存存入入一一个个元元素素时,HashSet会会调用用该对象象的的hashCode()方方法法来来得得到到该对象象的的hashCode()值,然然后后根根据据该hashCode值决决定
22、定该对象象在在HashSet中中的的存存储位位置置。如如果果有有两两个个元元素素通通过equals()方方法法比比较返返 回回 true,但但 它它 们 的的 hasCode()方方 法法 返返 回回 值 不不 同同,HashSet将将会会把把他他们存存储在在不不同同的的位位置置,依依然然可可以以添添加加成功成功。也也就就是是说,HashSet集集合合判判断断两两个个元元素素相相等等的的标准准是是两两 个个 对 象象 通通 过 equals()方方 法法 比比 较 相相 等等,并并 且且 两两 个个 对 象象 的的 hashCode()方法返回方法返回值也相等。也相等。如如果果两两个个对象象的
23、的hashCode()方方法法返返回回的的hasCode值相相同同,但但他他们通通过equals()方方法法比比较返返回回false时更更加加麻麻烦:因因为两两个个对象象的的hasCode()值相相同同,HashSet将将试图把把他他们保保存存在在同同一一个个位位置置,但但又又不不行行(否否则将将只只剩剩下下一一个个对象象),所所以以实际上上会会在在这个个位位置置用用链式式结构构来来保保存存多多个个对象象;而而HashSet访问集集合合元元素素时也也是是根根据据元元素素的的hashCode值来来快快速速定定位位的的,如如果果HashSet中中两两个个以以上上的的元元素素具具有有相相同同的的ha
24、shCode值,将将会会导致致性性能能下下降。降。如如果果两两个个对象象通通过equals()方方法法返返回回true,但但这两两个个对象象的的hashCode()返返回回不不同同的的hasCode()值时,这将将导致致HashSet会会把把这两两个个对象象保保存存在在Hash表表中中的的不不同同位位置置,从从而而使使两两个个对象象都都可可以以添添加加成成功功,这就就与与Set集合的集合的规则冲突了。冲突了。如如果果需需要要把把某某个个类的的对象象保保存存到到HashSet集集合合中中,重重写写这个个类的的equals()方方法法和和hashCode()方方法法时,应该尽尽量量保保证两两个个对
25、象象通通过equals()方方法法比比较返返回回true时,它它们的的hasCode()方法返回方法返回值也相同。也相同。HashSet中中每每个个能能存存储元元素素的的“槽槽位位”(slot)通通常常 称称 为“桶桶”(bucket),如如 果果 有有 多多 个个 元元 素素 的的hashCode值相相同同,但但它它们通通过equals()方方法法比比较返返回回false,就就需需要要在在一一个个“桶桶”里里放放多多个个元元素素,这样就就会会导致性能下降。致性能下降。重写重写hashCode()方法的基本方法的基本规则p在在程程序序运运行行过程程中中,同同一一个个对象象多多次次调用用hash
26、Code()方法方法应该返回相同的返回相同的值。p当当两两个个对象象通通过equals()方方法法返返回回true时,这两两个个对象的象的hashCode()方法方法应该返回相同的返回相同的值。p对象象中中用用作作equals()方方法法比比较标准准的的实例例变量量,都都应该用于用于计算算hashCode重写重写hashCode的一般步的一般步骤1.把把对象象内内每每个个有有意意义的的实例例变量量(即即每每个个参参与与equals()方方法法比比较标准准的的实例例变量量)计算算出出一一个个int类型型的的hasCode值。hashCode的的计算方式算方式实例例变量量类型型计算方式算方式实例例
27、变量量类型型计算方式算方式booleanhashCode=(f?0:1)floathashCode=Float.floatToIntBirs(f)整数类型(byte,short,char,int)hashCode=(int)fdoublelong1=Double.doubleToLongBits(f)hashCode=(int)(1(132);longhashCode=(int)(f(f32)引用类型hashCode=f.hashCode()2.用用第第一一步步计算算出出来来的的多多个个hashCode值组合合计算算出出一个一个hashCode值返回。返回。例如:例如:return f1.ha
28、shCode()+(int)f2;为了了避避免免直直接接相相加加产生生偶偶然然相相等等(两两个个对象象的的f1,f2实例例变量量并并不不相相等等,但但他他们的的hashCode的的和和恰恰好好相相等等),可可以以通通过为各各实例例变量量的的hashCode值乘乘以以任任意意一一个个质数再相加。例如如下代数再相加。例如如下代码:return f1.hashCode()*19+(int)f2*31;如如果果想想HashSet中中添添加加一一个个可可变对象象后后,后后面面程程序序修修改改了了该可可变对象象的的实例例变量量,则可可能能导致致它它与与集集合合中中的的其其他他元元素素相相同同(即即两两个个
29、对象象通通过equals()方方法法比比较返返回回true,两两个个对象象的的hashCode值也也相相等等),这就就有有可可能能导致致HashSet中包含两个相同的中包含两个相同的对象。象。实例例由由上上面面的的例例子子可可见,当当程程序序把把可可变对象象添添加加到到HashSet中中之之后后,尽尽量量不不要要去去修修改改该集集合合元元素素中中参参与与计算算hashCode()、equals()的的实例例变量量,否否则将将会会导致致HashSet无法正确操作无法正确操作这些集合元素。些集合元素。2.LinkedHashSet类HashSet还 有有 一一 个个 子子 类 LinkedHash
30、Set,LinkedHashSet集集合合也也是是根根据据元元素素的的hashCode值来来决决定定元元素素的的存存储位位置置,但但它它同同时使使用用链表表维护元元素素的的次次序序,这样使使得得元元素素看看起起来来是是以以插插入入的的顺序序保保存存的的。也也就就是是说,当当 遍遍 历 LinkedHashSet集集 合合 里里 的的 元元 素素 时,LinkedHashSet将将会会按按元元素素的的添添加加顺序序来来访问集集合合里里的的元素。元素。LinkedHashSet需需要要维护元元素素的的插插入入顺序序,因因此此性性能能略略低低于于HashSet的的性性能能,但但在在迭迭代代访问的的S
31、et里里的的全全部元素是有很好的性能,因部元素是有很好的性能,因为它以它以链表来表来维护内部内部顺序。序。实例例输入输入LinkedHashSet集合的元素时,元素的顺序总是集合的元素时,元素的顺序总是与添加顺序一致。与添加顺序一致。3.TreeSet类TreeSet是是 SortedSet接接 口口 的的 实 现 类,正正 如如SortedSet名名字字所所暗暗示示的的,TreeSet可可以以确确保保集集合合元元素素处于于排排序序状状态。与与HashSet集集合合相相比比,TreeSet还提提供供了几个了几个额外的方法:外的方法:pComparator comparator():如如果果Tr
32、eeSet采采用用了了定定制制排排序序,则该方方法法返返回回定定制制排排序序所所使使用用的的Comparator();如果;如果TreeSet采用了自然排序,采用了自然排序,则返回返回null。pObject first():返回集合中的第一个元素。返回集合中的第一个元素。pObject last():返回集合中的最后一个元素。返回集合中的最后一个元素。pObject lower(Object e):返返回回集集合合中中位位于于指指定定元元素素之之前前的的元元素素(即即小小于于指指定定元元素素的的最最大大元元素素,参参考考元元素素不需要是不需要是TreeSet集合里的元素)。集合里的元素)。p
33、Object higher(Object e):返返回回集集合合中中为与与指指定定元元素素之之后后的的元元素素(即即大大于于指指定定元元素素的的最最小小元元素素,参参考考元元素不需要是素不需要是TreeSet集合里的元素)。集合里的元素)。pSortedSet subSet(Object fromElement,Object toElement):返返 回回 此此 Set的的 子子 集集 合合,范范 围 从从fromElement(包含包含)到)到toElement(不包含)。(不包含)。pSortedSet headSet(Object toElement):返返回回此此Set的子集,由小于
34、的子集,由小于toElement的元素的元素组成。成。pSortedSet tailSet(Object fromElement):返返 回回 此此Set的子集,由大于或等于的子集,由大于或等于formElement的元素的元素组成。成。提提示示:表表面面上上看看起起来来这些些方方法法很很多多,其其实他他们很很简单:因因为TreeSet中中的的元元素素是是有有序序的的,所所以以增增加加了了访问第第一一个个,前前一一个个,后后一一个个,最最后后一一个个元元素素的的方方法法,并并提提供供了了三三个个从从TreeSet中中截截取取子子TreeSet的方法。的方法。练习与与HashSet集集合合采采用
35、用Hash算算法法来来决决定定元元素素的的存存储位位置置不不同同,TreeSet采采用用红黑黑树的的数数据据结构构来来春春初初集集合合元元素素。那那么么TreeSet进行行排排序序的的规则是是怎怎么么样的的呢呢?TreeSet支支持持两两种种排排序序方方法法:自自然然排排序序和和定定制制排排序序。在在默默认情况下,情况下,TreeSet采用自然排序采用自然排序。自然排序自然排序TreeSet会会调用用集集合合元元素素的的compareTo(Object obj)方方法法来来比比较元元素素之之间的的大大小小关关系系,然然后后将将集集合合元元素素按按升升序排列,序排列,这种方法就是自然排序。种方法
36、就是自然排序。java提提供供了了一一个个Comparable接接口口,该接接口口里里定定义了了一一个个compareTo(Object obj)方方法法,该方方法法返返回回一一个个整整数数值,实现该接接口口的的类必必须实现该方方法法,实现了了该接接口口的的类的的对象象就就可可以以比比较大大小小。当当一一个个对象象调用用该方方法法与与 另另 一一 个个 对 象象 进 行行 比比 较 时,例例 如如pareTo(obj2),如如果果该方方法法返返回回0,则表表明明这两两个个对象象相相等等;如如果果该方方法法返返回回一一个个正正整整数数,则表表明明obj1obj2;如如 果果该方方 法法 返返回回
37、 一一 个个 负 整整数数,则表表 明明obj1o2;如如果果该方方法法返返回回0,则表表明明01=02;如如果果该方法返回方法返回负整数,整数,则表明表明o102;如如果果需需要要实现定定制制排排序序则需需要要在在创建建TreeSet集集合合对象象时,提提 供供 一一 个个 Comparator对 象象 与与 该 TreeSet集集 合合 关关 联,由由 该Comparator对象象负责集集合合元元素素的的排排序序逻辑。由由于于Comparator是是一一个个函函数数式式接接口口,因因此此,可可以以使使用用Lambda表表达达式式来来代代替替Comparator表达式。表达式。实例例从大到小
38、排序:从大到小排序:上上 面面 程程 序序 中中 粗粗 体体 字字 部部 分分 使使 用用 了了 目目 标 类 型型 为Comparator的的Lambda表表达达式式,它它负责tsSet集集合合的的排排序序。所所以以当当把把M对象象添添加加到到ts集集合合中中时,无无须M类实现Comparator接接口口,因因为此此时TreeSet无无须通通过M对象象本本身身来来比比较大大小小,而而是是由由与与TreeSet关关联的的Lambda表表达达式式负责集合元素的排序。集合元素的排序。注意:注意:当当通通过Comparator对象象(或或Lambda表表达达式式)来来实现TreeSet的的定定制制排
39、排序序时,依依然然不不可可以以向向TreeSet中中添添加加类型型不不同同的的对象象,否否则会会引引发ClassCastException异异常常,使使用用定定制制排排序序时,TreeSet对集集合合元元素素排排序序不不管管集集合合元元素素本本省省的的大大小小,而而是是由由Comparator对象象(或或Lambda表表达达式式)负责集集合合元元素素的的排排序序规则。TreeSet判判断断两两个个元元素素相相等等的的标准准是是:通通过Comparator(或或Lambda表表达达式式)比比较连个个元元素素返返回回了了0,这样TreeSet不会把第二个元素添加到集合中。不会把第二个元素添加到集合
40、中。4.EnumSet类EnumSet是是 一一 个个 专 为 枚枚 举 类 设 计 的的 集集 合合 类,EnumSet中中的的所所有有元元素素都都必必须是是指指定定枚枚举类型型的的枚枚举值,该枚枚举类型型在在创建建EnumSet时显式式或或隐式式的的地地指指定定。EnumSet的的集集合合元元素素也也是是有有序序的的,EnumSet以以枚枚举值在在Enum类内的定内的定义顺序来决定集合元素的序来决定集合元素的顺序。序。EnumSet在在内内部部以以位位向向量量的的形形式式存存储,这种种存存储形形式式非非常常紧凑凑、高高效效,因因此此EnumSet对象象占占用用内内存存很很小小,而而且且运运
41、行行效效率率很很好好。尤尤其其是是进行行批批量量操操作作(如如调用用containsAll()和和retainAll())时,如如果果其其参参数数也也是是EnumSet集集合合,则该批量操作的批量操作的执行速度也非常快。行速度也非常快。EnumSet集集合合不不允允许加加入入null元元素素,如如果果试图插插入入null元元素素,EnumSet将将抛抛出出NullPointerException异异常常。如如果果只只是是想想判判断断EnumSet是是否否包包含含NULL元元素素或或试图删除除null元元素素都都不不会会抛抛出出异异常常,只只是是删除除操操作作将将返返回回false,因,因为没有
42、任何没有任何NULL元素被元素被删除。除。EnumSet类没没有有暴暴露露任任何何构构造造器器来来创建建该类的的实例例,程序程序应该通通过他提供的他提供的类方法来方法来创建建EnumSet对象。象。EnumSet类提提供供了了如如下下常常用用的的类方方法法来来创建建EnumSet对象。象。pEnumSet allOf(Class elementType):创建建一一个个包包含含指定枚指定枚举类里所有枚里所有枚举值得得EnumSet集合。集合。pEnumSet complementOf(EnumSet s):创建建一一个个其其元元 素素 类 型型 与与 指指 定定 EnumSet里里 元元 素素
43、 类 型型 相相 同同 的的EnumSet集集合合,新新EnumSet集集合合包包含含原原EnumSet集合所不包含的、此枚集合所不包含的、此枚举类剩下的枚剩下的枚举值。pEnumSet copyOf(Collection c):使使用用一一个个普普通通集集合合来来创建建EnumSet集合。集合。pEnumSet copyOf(EnumSet s):创建建一一个个与与指指定定EnumSet具具有有相相同同元元素素类型型、相相同同集集合合元元素素的的EnumSet集合。集合。pEnumSet noneOf(Class elementType):创建建一一个个元素元素类型型为指定枚指定枚举类型的空
44、型的空EnumSet。pEnumSet of(E first,E.rest):创建建一一个个包包含含一一个个或或多多个个枚枚举值的的EnumSet集集合合,传入入的的多多个个枚枚举值必必须属于同一个枚属于同一个枚举类。pEnumSet range(E from,E to):创建建一一个个包包含含从从from枚枚 举 值 到到 to枚枚 举 值 范范 围 内内 所所 有有 枚枚 举 值 的的EnumSet集合。集合。实例例除除了了以以上上实例例的的方方法法,还可可以以复复制制另另一一个个EnumSet集集合合中中的的所所有有元元素素来来创建建新新的的EnumSet集集合合,或或者者复复制制另另一
45、一个个Collection集集合合中中的的所所有有元元素素来来创建建新新的的EnumSet集集合合。当当复复制制Collection集集合合中中的的所所有有元元素素来来创建建新新的的EnumSet集集合合是是,要要求求Collection集集合合中中的的所所有有元元素素必必须是是同同一一个个枚枚举类型型的的枚枚举值,否否则就就会会发生生ClassCastException异常。异常。实例例5.各各Set实现类的性能分析的性能分析HashSet和和TreeSet是是Set的的两两个个典典型型实现,到到底底如如何何选择HashSet和和TreeSet呢呢?HashSet的的性性能能总是是比比Tre
46、eSet好好(特特别是是最最常常用用的的添添加加、查询元元素素等等操操作作),因因为TreeSet需需要要额外外的的红黑黑树算算法法来来维护集集合合元元素素的的次次序序。只只有有当当需需要要一一个个保保存存排排序序的的Set是是,才才应该使使用用TreeSet,否,否则都都应该使用使用HashSet。HashSet还有有一一个个子子类:LinkedHashSet,但但它它只只能保存同一个枚能保存同一个枚举类值作作为集合元素。集合元素。必必 须 指指 出出 的的 是是,set的的 三三 个个 实 现 类 HashSet、TreeSet和和EnumSet都都是是线程程不不安安全全的的。如如果果有有
47、多多个个线程程同同时访问一一个个Set集集合合,并并且且有有超超过一一个个线程程修修改改了了该Set集集合合,则必必须手手动保保证该Set集集合合的的同同步步性性。通通常常可可以以通通过Collection工工具具类的的synchronizedSortedSet方方法法来来“包包装装”该Set集集合合。此此操操作作最最好好在在创建建时进行行,以防止以防止对Set集合的意外非同步集合的意外非同步访问。例如:。例如:SortedSet s=Collections.synchronizedSortedSet(new TreeSet(.);第四第四节 List集合集合List集集合合代代表表一一个个元
48、元素素有有序序、可可重重复复的的集集合合,集集合合中中每每个个元元素素都都有有其其对应的的顺序序索索引引。List集集合合允允许使使用用重重复复元元素素,可可以以通通过索索引引来来访问来来访问指指定定的的集集合合元元素素。List集合默集合默认按元素的添加按元素的添加顺序序设置元素的索引。置元素的索引。1.Java 8 改改进的的List接口和接口和ListIterator接口接口List作作为Collection接接口口的的子子接接口口,当当然然可可以以使使用用Collection接接口口里里的的全全部部方方法法。而而且且由由于于List是是有有序序集集合合,因因此此List集集合合里里增增
49、加加了了一一些些根根据据索索引引来来操操作作集集合合元元素的方法。素的方法。pvoid add(int index,Object element):将将 元元 素素element插入到插入到List集合的集合的index处。pboolean addAll(int index,Collection c):将将集集合合c所包含的所有元素都插入到所包含的所有元素都插入到List集合的集合的index处。pObject get(int index):返回集合返回集合index索引索引处的元素。的元素。pint indexOf(Object o):返返回回对象象o在在List集集合合中中第第一一次出次出
50、现的位置索引。的位置索引。pint indexOf(Object o):返返回回对象象o在在List集集合合中中第第一一次出次出现的位置索引。的位置索引。pint lastIndexOf(Object o):返返回回对象象o在在List集集合合中中最后一次出最后一次出现的位置索引。的位置索引。pObject remove(int index):删除除并并返返回回index索索引引处的元素。的元素。pObject set(int index,Object element):将将index索索引引处的的元元素素替替换成成element对象象,返返回回被被替替换的的旧旧元元素。素。pList sub