Java高级知识复盘之集合
集合是一种容器,相较于数组容器,集合可以无限添加数据,无需考虑元素的移动,而且集合中有较多的数据结构可供选择,但是集合中都是对象,不能出现基本数据类型,所以需要使用包装类。
可以实现集合的接口分为:
Collection接口
List接口
Set接口
Map接口
Collection接口
Collection接口下的集合都是 单值。
接口中定义的常用方法:
add():添加
addAll():一次性添加多个对象
remove():删除指定内容
removeAll():一次性删除多个对象
containsAll():是否包含指定集合中所有的元素对象
clear():清空
toArray():把Collection集合对象转换为一个Object数组
List接口
实现了List接口实现类中的集合元素是有序(是存取有序 索引 也是从0开始)而且可以重复(集合元素对象可以相等)
常用方法:
get():根据指定索引获取集合元素对象
set():更改对象内容,用新的对象去替换指定索引的所对应的对象
insert():插入指定索引进行插入
remove():根据索引删除
indexOf():指定对象首次出现的索引值
lastIndexOf():指定对象最后一次出现的索引值
实现类
ArrayList
-
ArrayList的底层是一个Object数组,来存放集合元素对象
-
第一次扩容的时候是指向一个长度为10的Object数组;第二次扩容的时候 长度为15 ,22,33,规则为上一次长度的一半,不算余数
-
创建ArrayList对象的时候,推荐使用有参构造避免进行多次无效扩容,可以给一个预估值
-
ArrayList 底层是一个Object数组,数组的内存空间是连续的;
-
数组的查询性能较高,查询的时间复杂度是O(1) 和元素个数没有关系;
-
指定位置新增(插入)和删除的时候性能较低,因为内部要进行元素移动新增和删除时间复杂度是O(n);
-
LinkedList
-
链表分为单向链表和双向链表,链表元素之间内存不连续
-
底层是双向链表;
-
LinkedList的查询性能较低,查询时间复杂度O(n); 但是指定位置新增和删除性能比较高,只涉及到前后节点的指向的改动
Vector
-
Vector底层也是Object数组,和ArrayList 一样
-
Vector是线程安全的,可以在多线程项目中应用;
-
ArrayList和LinkedList都是线程不安全的,不能在多线程中使用,否则会出现线程安全问题
Set接口
-
集合元素都是单值
-
实现了Set接口实现类中的集合元素是无序(没有索引)而且不可重复
实现类
HashSet
HashSet内部使用的是HashMap存储对象,可以理解为是HashMap的副产品
LinkedHashSet
LinkedHashSet 是HashSet的子类 内部是 LinkedHashMap存储对象,维持元素的添加顺序
TreeSet
TreeSet内部使用的是 TreeMap 存储对象
Map接口
-
Map 集合元素都是成对的值 Key-Value键值对(主键),一对才算一个集合元素
-
由Key映射出来Value,每一个唯一的Key都能对应一个Value
-
Map中的Key对象是不可重复的 比如身份证号(ID)-> Person对象 单车Id -> 单车对象
接口中定义的常用方法:
put():添加对象
get():根据Key对象获取其所对应的value对象
equals():判断是否相等
size():集合长度
isEmpty():是否为空
containsKey():是否包含指定的Key对象
containsValue():是否包含指定的Value对象
remove():根据指定的Key对象删除此键值对
实现类
HashMap
-
HashMap 底层是哈希表(数组+单向链表+红黑树,在JDK8及之后加入了红黑树 ),哈希表中使用了哈希算法;
-
加入红黑树的原因是为了提高单向链表的查询性能
-
红黑树其实也是一颗二叉搜索树,树中的节点有序 左子树都是小于根节点的 右子树都是大于根节点的
-
红黑树查询时间复杂度 O(log2n) 单向链表查询时间复杂度是O(n)
-
HashMap 结合了数组和链表的优势
-
调用无参构造创建HashMap 内部数组第一次初始化的时候长度是16,以后都是 以2倍进行扩容 32 64 128 ;保证数组的长度都是2的指数值;
-
推荐使用HashMap的有参构造,避免进行多次无效扩容浪费性能
LinkedHashMap
-
LinkedHashMap是HashMap 的子类;
-
底层是哈希表(数组+链表+红黑树)+双向链表,为了维持元素的添加顺序
TreeMap
-
底层是红黑树 二叉排序树 树节点有顺序,插入的时候要根据Key对象比较大小
-
内部要进行排序 ,要求Key类型是可以比较大小的
-
要求Key类型要么实现Comparable接口 ,要么提供一个外部的比较器
Hashtable
-
底层是哈希表(数组+链表)
-
Hashtable是线程安全,HashMap是线程不安全
-
Hashtable 虽然线程安全 但是性能较低,ConcurrentHashMap 是线程安全的; 性能较高
-
单线程应用中使用HashMap,多线程应用中 使用 ConcurrentHashMap