文章目录
一、集合框架
简化图
说明:对于以上的框架图有如下几点说明
1.所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。
2. 集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。
3. 抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。
4. 实现类:8个实现类(实线表示),对接口的具体实现。
5. Collection 接口是一组允许重复的对象。
6. Set 接口继承 Collection,集合元素不重复。
7. List 接口继承 Collection,允许重复,维护元素插入顺序。
8. Map接口是键-值对象,与Collection接口没有什么关系。
9.Set、List和Map可以看做集合的三大类:
List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。
Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。
Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。
总体分析
大致说明:
看上面的框架图,先抓住它的主干,即Collection和Map。
1、Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。Collection包含了List和Set两大分支。
(1)List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。List的实现类有LinkedList, ArrayList, Vector, Stack。
(2)Set是一个不允许有重复元素的集合。Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。
2、Map是一个映射接口,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。AbstractMap是个抽象类,它实现了Map接口中的大部分API。而HashMap,TreeMap,WeakHashMap都是继承于AbstractMap。Hashtable虽然继承于Dictionary,但它实现了Map接口。
3、接下来,再看Iterator。它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。我们说Collection依赖于Iterator,是因为Collection的实现类都要实现iterator()函数,返回一个Iterator对象。ListIterator是专门为遍历List而存在的。
4、再看Enumeration,它是JDK 1.0引入的抽象类。作用和Iterator一样,也是遍历集合;但是Enumeration的功能要比Iterator少。在上面的框图中,Enumeration只能在Hashtable, Vector, Stack中使用。
5、最后,看Arrays和Collections。它们是操作数组、集合的两个工具类。
有了上面的整体框架之后,我们接下来对每个类分别进行分析。
Collection接口
Collection接口是处理对象集合的根接口,其中定义了很多对元素进行操作的方法。Collection接口有两个主要的子接口List和Set,注意Map不是Collection的子接口,这个要牢记。
Collection:集合接口 作用是存储一组不唯一,无序的对象
List接口: 作用是存储一组不唯一,有序的对象
Set接口: 作用是存储一组唯一,无序的对象
List接口的实现类
List包含两个实现类:ArrayList和LinkedList
ArrayList以数组作为底层存储,实现了长度可变的数组,在内存中分配连续的空间,遍历元素和随机访问元素的效率比较高
add()方法插入元素(add(Object o),add(int index,Object o))
1、插入前先判断容量是否越界,则扩容
(1)扩容后比数组最大长度大,则是int的最大值作为数组长度
还没达到数组最大长度,则就是数组最大长度
(2)正常来说扩容1.5倍,如果扩容1.5倍以后还不够,
则直接把当前长度赋值给数组新长度
(3)如果是新数组和把长度与10比较,大的赋值给新数组长度
2、不需要扩容则直接插入
LinkedList以链表作为底层存储,采用链表存储方式,插入、删除元素时效率比较高
链表:多个node互相存储地址,以下一个node的地址存储
遍历很不方便,增加node和删除node会很快
Vector: ArrayList的线程安全版,在多线程的状况下使用
ArrayList常用方法
方法名 | 说明 |
---|---|
boolean add(Object o) | 在列表的末尾顺序添加元素,起始索引位置从0开始 |
void add(int index,Object o) | 在指定的索引位置添加元素。索引位置必须介于0和列表中元素个数之间 |
int size() | 返回列表中的元素个数 |
Object get(int index) | 返回指定索引位置处的元素。取出的元素是Object类型,使用前需要进行强制类型转换 |
boolean contains(Object o) | 判断列表中是否存在指定元素 |
boolean remove(Object o) | 从列表中删除元素 |
Object remove(int index) | 从列表中删除指定位置元素,起始索引从0开始 |
Object set(int index,Object o) | 指定下标进行修改其中的元素,返回的是修改前的对象 |
Collection接口常用通用方法还有:
clear()、isEmpty()、iterator()、toArray()
LinkedList常用方法
方法名 | 说明 |
---|---|
void addFirst(Object o) | 在列表的首部添加元素 |
void addLast(Object o) | 在列表的末尾添加元素 |
Object getFirst() | 返回列表中的第一个元素 |
Object getLast() | 返回列表中的最后一个元素 |
Object removeFirst() | 删除并返回列表中的第一个元素 |
Object removeLast() | 删除并返回列表中的最后一个元素 |
Set接口
Set接口存储一组唯一,无序的对象
HashSet是Set接口常用的实现类
Set中存放对象的引用
Set接口判断加入对象是否已经存在的方法:采用对象的equals()方法比较两个对象是否相等
HashSet:是以HashMap的key值的hash码来进行存储(保证唯一,理论上)
Set接口没有get()方法,无法按下标查找或遍历
遍历集合的方法:
1、通过for循环来遍历
2、通过迭代器Iterator实现遍历
获取Iterator :Collection 接口的iterator()方法
Iterator的方法
boolean hasNext(): 判断是否存在另一个可访问的元素
Object next(): 返回要访问的下一个元素
3、增强型for循环
Map接口
Map接口专门处理键值映射数据的存储,可以根据键实现对值的操作
Map接口最常用的实现类是HashMap
Map接口常用方法
方法名 | 说明 |
---|---|
Object put(Object key,Object val) | 以“键-值”对的方式进行存储 |
Object get(Object key) | 根据键返回相关联的值,如果不存在指定的键,返回null |
Object remove(Object key) | 删除由指定的键映射的“键-值”对 |
int size() | 返回元素个数 |
Set keySet() | 返回键的集合 |
Collection values() | 返回值的集合 |
boolean containsKeys(Object key) | 如果存在由指定的键映射的“键-值”对,返回true |
遍历Map集合
方法1:通过迭代器Iterator实现遍历
Map<String, String> map = new HashMap<String, String>();
Iterator<Map.Entry<String, String>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
方法2:增强型for循环
Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
String value = map.get(key);
System.out.println("Key = " + key + ", Value = " + value);
}
方法3:键值对
//获取键
Set keys = map.keySet();
for (Object key : keys) {
System.out.println(key);
System.out.println(map.get(key));
}
//获取值
Collection values = map.values();
for (Object value : values) {
System.out.println(value);
}
Map接口注意事项:
包含接口Entry<K,V>
在HashMap中使用Node节点实现了Entry“键-值”对
Node节点用next属性实现了单向链表
map底层entry+单向链表,数组+单向链表
当元素节点个数超过8时,转用红黑树进行底层存储
使用map.remove(Object key,Object value)方法进行删除操作时,必须要key和value都匹配时才能删除
map.put(Object key,Object value)在被用作修改时,与map.replace(Object key,Object value)作用基本一致