集合


1、 集合概述
Java的集合类是一些常用的数据结构,例如:队列、栈、链表等。Java集
合就像一种“容器”,用于存储数量不等的对象,并按照规范实现一些常用的操作和算法。程序员在使用Java的集合类时,不必考虑数据结构和算法的具体实现细节,根据需要直接使用这些集合类并调用相应的方法即可,从而提高了开发效率。

2、集合框架
• 在JDK 5.0之前,Java集合会丢失容器中所有对象的数据类型,将所有对象都当成Object类型进行处理。从JDK 5.0增加泛型之后,Java集合完全支持泛型,可以记住容器中对象的数据类型,从而可以编写更简洁、健壮的代码。
• Java所有的集合类都在java.util包下,从JDK 5.0开始为了处理多线程环境下的并发安全问题,又在java.util.concurrent包下提供了一些多线程支持的集合类。
• Java的集合类主要由两个接口派生而出:Collection和Map,这两个接口派生出一些子接口或实现类。

Collection集合体系
Collection接口下有3个子接口:
• Set接口:无序、不可重复的集合;
• Queue接口:队列集合;
• List接口:有序、可以重复的集合。

Map集合体系
• 所有Map的实现类用于保存具有映射关系的数据,即Map保存的每项数据都是由key/value键/值对组成。Map中的key用于标识集合中的每项数据,是不可重复的,可以通过key来获取Map集合中的数据项。
Java中的集合分为三大类:
• Set集合:将一个对象添加到Set集合时,Set集合无法记住添加的顺序 ,因此Set集合中的元素不能重复,否则系统无法识别该元素,访问Set 集合中的元素也只能根据元素本身进行访问;
• List集合:与数组类似,List集合可以记住每次添加元素的顺序,因此可以根据元素的索引访问List集合中的元素,List集合中的元素可以重复且长度是可变的;
• Map集合:每个元素都是有key/value键值对组成,可以根据每个元素的key来访问对应的value,Map集合中的key不允许重复,value可以重复 。

3、迭代器接口
• 迭代器(Iterator)可以采用统一的方式对Collection集合中的元素进行遍历操作,开发人员无需关心Collection集合中的内容,也不必实现IEnumerable或者IEnumerator接口就能够使用foreach循环遍历集合中的部
分或全部元素。
• Java从JDK 5.0开始增加了Iterable新接口,该接口是Collection接口的父接口,因此所有实现了Iterable的集合类都是可迭代的,都支持foreach循环遍历。Iterable接口中的iterator()方法可以获取每个集合自身的迭代器Iterator。Iterator是集合的迭代器接口,定义了常见的迭代方法,用于访
问、操作集合中的元素。
• Collection集合中的实现类都实现了Iterable接口中的iterator()方法,因此都可以通过iterator()方法获取集合自身的迭代器。Java 8为Iterable接口新增了一个默认forEach()方法,该方法所需的参数是Lambda表达式,更加简化了集合的迭代操作。

4、 Collection接口
• Collection接口是Set、Queue和List接口的父接口,该接口中定义的方法
可以操作这三个接口中的任一个集合
使用Collection需要注意以下几点问题:
• add()、addAll()、remove()、removeAll()和retainAll()方法可能会引发不支持该操作的UnsupportedOperationException异常;
• 将一个不兼容的对象添加到集合中时,将产生ClassCastException异常; • Collection接口没有提供获取得某个元素的方法,但可以通过iterator()方法获取迭代器来遍历集合中的所有元素;
• 虽然Collection中可以存储任何Object对象,但不建议在同一个集合容器中存储不同类型的对象,建议使用泛型增强集合的安全性,以免引起
ClassCastException异常。

5、List接口及其实现类
• List是Collection接口的子接口,可以使用Collection接口中的全部方法。因为List是有序、可重复的集合,所以List接口中又增加一些根据索引操作集合元素的方法。
• List集合默认按照元素添加顺序设置元素的索引,索引从0开始,例如:第一次添加的元素索引为0,第二次添加的元素索引为1,第n次添加的元素索引为n-1。当使用无效的索引时将产生IndexOutOfBoundsException异常。
• ArrayList和Vector是List接口的两个典型实现类,完全支持List接口的所有功能方法。ArrayList称为“数组列表”,而Vector称为“向量”,两者都是基于数组实现的列表集合,但该数组是一个动态的、长度可变的、并允许再分配的Object[]数组。
• ArrayList和Vector在用法上几乎完全相同,但由于Vector从JDK 1.0开始就有了,所以Vector中提供了一些方法名很长的方法,例如:addElement()方法,该方法跟add()方法没有任何区别。
ArrayList和Vector虽然在用法上相似,但两者在本质上还是存在区别的:
• ArrayList是非线程安全的,当多个线程访问同一个ArrayList集合时,如果多个线程同时修改ArrayList集合中的元素,则程序必须手动保证该集合的同步性;
• Vector是线程安全的,程序无需手动保证该集合的同步性。正因为Vector是线程安全的,所以Vector的性能要比ArrayList低。在实际应用中,即使要保证线程安全,也不推荐使用Vector,因为可以使用Collections工具类将一个ArrayList变成线程安全的。

6、Set接口及其实现类
Set集合类似一个罐子,可以将多个元素丢进罐子里,但不能记住元素的添加顺序,因此不允许包含相同的元素。Set接口继承Collection接口,没有提供任何额外的方法,其用法与Collection一样,只是特性不同(Set中的元素不重复) 。
Set接口常用的实现类包括HashSet、TreeSet和EnumSet,这三个实现类各具特色:
• HashSet是Set接口的典型实现类,大多数使用Set集合时都使用该实现类。HashSet使用Hash算法来存储集合中的元素,具有良好的存、取以及查找性;
• TreeSet采用Tree“树”的数据结构来存储集合元素,因此可以保证集合中的元素处于排序状态。TreeSet支持两种排序方式:自然排序和定制排序,默认情况下采用自然排序;
• EnumSet是一个专为枚举类设计的集合类,其所有元素必须是指定的枚举类型。EnumSet集合中的元素也是有序的,按照枚举值顺序进行排序。

HashSet及其子类都是采用Hash算法来决定集合中元素的存储位置,并通过Hash算法来控制集合的大小。Hash表中可以存储元素的位置称为“(bucket)”,通常情况下,单个桶只存储一个元素,此时性能最佳,Hash算法可以根据HashCode值计算出桶的位置,并从桶中取出元素。但当发生Hash冲突时,单个桶会存储多个元素,这些元素以链表的形式存储。

7、 Queue接口及其实现类
• 队列Queue通常以“先进先出(FIFO)”的方式排序各个元素,即最先入队的元素最先出队。Queue接口继承Collection接口,除了Collection接口中的基本操作外,还提供了队列的插入、提取和检查操作,且每个操作都存在两种形式:一种操作失败时抛出异常;另一种操作失败时返回一个特殊值(null或false) 。
• 链接列表LinkedList是Deque和List两个接口的实现类,兼具队列和列表两
种特性,是最常使用的集合类之一。LinkedList不是基于线程安全的,如果
多个线程同时访问一个LinkedList实例,而其中至少有一个线程从结构上修
改该列表时,则必须有外部代码手动保持同步。
ArrayDeque称为“数组双端队列”,是Deque接口的实现类,其特点如下:
• ArrayDeque没有容量限制,可以根据需要增加容量;
• ArrayDeque不是基于线程安全的,在没有外部代码同步时,不支持多个 线程的并发访问;
• ArrayDeque禁止添加null元素;
• ArrayDeque在用作堆栈时快于Stack,在用作队列时快于LinkedList。

PriorityQueue是Queue接口的实现类,是基于优先级的、无界队列,通常称为“优先级队列”。优先级队列的元素按照其自然顺序进行排序,或定制排序,优先级队列不允许使用null元素。依靠自然顺序的优先级队列不允许插入不可比较的对象。

8、 Map接口及其实现类
• Map接口是集合框架的另一个根接口,与Collection接口并列。Map是以key/value 键值对映射关系存储的集合。
HashMap和TreeMap是Map体系中两个常用实现类,其特点如下:
• HashMap是基于哈希算法的Map接口的实现类,该实现类提供所有映射操
作,并允许使用null键和null值,但不能保证映射的顺序,即是无序的映射集合;
• TreeMap是基于“树”结构来存储的Map接口实现类,可以根据其键的自然顺序进行排序,或定制排序方式。
 

你可能感兴趣的:(集合)