容器说明
容器(集合)是用来存储和组织其他对象的对象,当我们需要将一些相同结构的个体整合在一起时,就可以考虑使用集合了。为什么使用集合而不是数组?
- 集合和数组相似点
1.1 都可以存储多个对象,对外作为一个整体存在 - 数组的缺点
2.1 长度必须在初始化时指定,且固定不变
2.2 数组采用连续存储空间,删除和添加效率低下
2.3 数组无法直接保存映射关系
2.4 数组缺乏封装,操作繁琐
集合架构
Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中
- Collection 接口存储一组不唯一,无序的对象
- List 接口存储一组不唯一,有序(索引顺序)的对象
- Set 接口存储一组唯一,无序的对象
- Map接口存储一组键值对象,提供key到value的映射
4.1 Key 唯一 无序
4.2 value 不唯一 无序
List
- List
- 特点:有序 不唯一(可重复)
- ArrayList 线性表中的顺序表
- 在内存中分配连续的空间,实现了长度可变的数组
- 优点:遍历元素和随机访问元素的效率比较高
- 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低
- 源码解析:ArrayList底层存储是一个Object类型数组
- LinkedList 线性表中双向链表
- 采用双向链表存储方式。
- 缺点:遍历和随机访问元素效率低下
- 优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发 生在头尾可以减少查询次数)
- 源码解析:LinkedList双向链表存储结构
Set
- Set
- 特点:无序 唯一(不重复)
- HashSet
- 采用Hashtable哈希表存储结构(神奇的结构)
- 优点:添加速度快 查询速度快 删除速度快
- 缺点:无序
- 源码解析:HashSet底层存储元素就是一个HashMap,HashSet的值就存储在map的key上,value是一个默认常量。所以HashSet自带唯一属性
- LinkedHashSet
- 采用哈希表存储结构,同时使用链表维护次序
- 有序(添加顺序)
- TreeSet
- 采用二叉树(红黑树)的存储结构
- 优点:有序 查询速度比List快(按照内容查询)
- 缺点:查询速度没有HashSet快
Map
- Map
- 特点 key-value映射
- HashMap
- Key无序 唯一 (Set)
- Value 无序 不唯一 (Collection)
- LinkedHashMap
- 有序的HashMap 速度快
- TreeMap
- 有序 速度没有hash快
Iterator
所有集合类均未提供相应的遍历方法,而是把把遍历交给迭代器完成。迭代器为集 合而生,专门实现集合遍历
-
Iterator是迭代器设计模式的具体实现
-
Iterator方法
- boolean hasNext(): 判断是否存在另一个可访问的元素
- Object next(): 返回要访问的下一个元素
- void remove(): 删除上次访问返回的对象。
-
For-each循环
- 增强的for循环,遍历array 或 Collection的时候相当简便
- 无需获得集合和数组长度,无需使用索引访问元素,无需循环条件
- 遍历集合时底层调用Iterator完成操作
-
For-each缺陷:
- 数组:
- 不能方便的访问下标值
- 不要在for-each中尝试对变量赋值,只是一个临时变量
- 集合:
- 与使用Iterator相比,不能方便的删除集合中的内容
- 数组:
-
For-each总结:
- 除了简单遍历并读出其中的内容外,不建议使用增强for
-
ListIterator和Iterator的关系
- public interface ListIterator extends Iterator
- 都可以遍历List
-
ListIterator和Iterator的区别
-
使用范围不同
- Iterator可以应用于更多的集合,Set、List和这些集合的子类型。
- 而ListIterator只能用于List及其子类型。
-
遍历顺序不同
- Iterator只能顺序向后遍历; ListIterator还可以逆序向前遍历
- Iterator可以在遍历的过程中remove();ListIterator可以在遍历的过程中remove()、add()、set()
-
-
ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
旧的集合类
- Vector
- 实现原理和ArrayList相同,功能相同,都是长度可变的数组结构,很多情况下可以互用
- 两者的主要区别如下
- Vector是早期JDK接口,ArrayList是替代Vector的新接口
- Vector线程安全,效率低下;ArrayList重速度轻安全,线程非安全
- 长度需增长时,Vector默认增长一倍,ArrayList增长50%
- Hashtable类
- 实现原理和HashMap相同,功能相同,底层都是哈希表结构,查询速度快,很多情况下可互用
- 两者的主要区别如下
- Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口
- Hashtable继承Dictionary类,HashMap实现Map接口
- Hashtable线程安全,HashMap线程非安全
- Hashtable不允许null值,HashMap允许null值
新的线程同步集合类
- 早期集合类Vector、Hashtable:线程安全的
- 是怎么保证线程安排的,使用synchronized修饰方法
- 为了提高性能,使用ArrayList、HashMap替换,线程不安全,但是性能好。使用ArrayList、 HashMap,需要线程安全怎么办呢?
- 使用Collections.synchronizedList(list);Collections.synchronizedMap(m);解决
- 底层使用synchronized代码块锁
- 虽然也是锁住了所有的代码,但是锁在方法里边,并所在方法外边性能可以理解为稍有提高吧。 毕竟进方法本身就要分配资源的
- 在大量并发情况下如何提高集合的效率和安全呢?
- 提供了新的线程同步集合类,委员java.util.concurrent包下,使用Lock锁
- ConcurrentHashMap、CopyOnWriteArrayList 、CopyOnWriteArraySet:
- 注意 不是CopyOnWriteHashSet
集合总结
集合和数组的比较
- 数组不是面向对象的,存在明显的缺陷,集合完全弥补了数组的一些缺点,比数组更灵活更实 用,可大大提高软件的开发效率而且不同的集合框架类可适用于不同场合。具体如下:
- 数组容量固定且无法动态改变,集合类容量动态改变。
- 数组能存放基本数据类型和引用数据类型的数据,而集合类中只能放引用数据类型的数据。
- 数组无法判断其中实际存有多少元素,length只告诉了array容量;集合可以判断实际存有多 少元素,而对总的容量不关心
- 集合有多种数据结构(顺序表、链表、哈希表、树等)、多种特征(是否有序,是否唯一)、 不同适用场合(查询快,便于删除、有序),不像数组仅采用顺序表方式
- 集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可 实现各种复杂操作,大大提高软件的开发效率。
ArrayList和LinkedList 的联系和区别
- 联系:
- 都实现了List接口
- 有序 不唯一(可重复)
- ArrayList
- 在内存中分配连续的空间,实现了长度可变的数组
- 优点:遍历元素和随机访问元素的效率比较高
- 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低,
- LinkedList
- 采用链表存储方式。
- 缺点:遍历和随机访问元素效率低下
- 优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾 可以减少查询次数)
Vector和ArrayList的联系和区别
- 实现原理相同,功能相同,都是长度可变的数组结构,很多情况下可以互用
- 两者的主要区别如下
- Vector是早期JDK接口,ArrayList是替代Vector的新接口
- Vector线程安全,效率低下;ArrayList重速度轻安全,线程非安全
- 长度需增长时,Vector默认增长一倍,ArrayList增长50%
HashMap和Hashtable的联系和区别
- 实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用
- 两者的主要区别如下
- Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口
- Hashtable继承Dictionary类,HashMap实现Map接口
- Hashtable线程安全,HashMap线程非安全
- Hashtable不允许null值,HashMap允许null值
Collection和Collections的区别
- Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口 List和Set。
- Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对 各种集合的搜索、排序、线程安全化等操作。
丶clearwater