Java的集合主要有两种,由Collection和map两个接口派生出来,Collection接口下有List、Set、Queue三种,存放单一的数据;Map接口下有HashMap、HashTable、SortedMap三种,以key-value的形式存放数据。如下图是集合的继承关系
List、set、queue、map的区别
List:存放的数据具有有序性和可重复性的特点
Set:存放的数据具有唯一性不能重复
queue:具有队列的特点,存入的数据先进先出,数据可以重复
map:key-value结构,key是不能重复,不能为空,value可以重复也可以为空
下面结合底层数据结构了解下这四种接口
List
ArrayList底层数据结构是object[];
vector底层数据结构是Object[];
linkedList底层数据结构是双链表
set
HashSet:是基于HashMap实现的,实现自动排序功能
如下图
打印内容:
1
2
3
5
LinkedHashSet:是HashSet的一个子类,其底层是基于LinkedHashMap实现的。
打印内容:
5
3
4
0
1
TreeSet:底层是红黑树
Queue
PriorityQueue:底层是基于Object[] 数组实现的小顶堆
DelayQueue:通过PriorityQueue实现
ArrayDeque:可扩容动态双向数组
Map
HashMap:在jdk1.8之前hashMap是有数组加链表组成,数组中存放的是链表,链表的存在是为了解决hash冲突的问题。当put数据时,首先计算中key的hash值,根据hash值确定数据在数组中的位置(也就是下标),如果hash值不存在,直接写入数组。如果hash值存在,当key相同时,会直接覆盖调旧的数据,当key不相同(hash值出现冲突)后,数据会存放在链表中。在jdk1.8后,为了解决hash冲突的问题,引入了红黑树,当链表的长度大于8时,链表会自动转为红黑树(当然在判断是否转为红黑树时,会判断数组的长度是否大于64,如果未大于64,优先扩充数组的长度)。
hashMap put的流程:
1、看过源码的同学应该都知道,我们正常new HashMap时是没有初始化table数组的,在put的时候才判断数组是否为空,如果为空才会扩容table数组
2、当table数组不为空时,计算key的hash值,如果hash值数组中不存在直接插入value在hash对应的下标中
3、如果hash值已经存在,并且key也相同,直接替换旧的value
4、如果hash值已经存在,但是与对应的旧key不相同,也就是说发生了hash冲突,那根据数据为在链表还是红黑树,根据对应的数据写入的逻辑,写入新的value值
LinkedHashMap:是hashMap的子类,与HashMap的唯一区别就是在HashMap实现的基础上引入双向链表保证数据的有序性,key是可以存放null的,HashMap key不能存入null
ArrayList与Array(数组)的区别
1、ArrayList:是基于动态数组实现,长度可根据数据的长度动态扩容和缩容,Array的长度不能动态扩展
2、ArrayList支持通过泛型保证数据的安全性,Array是不支持的
3、ArrayList有提供丰富的api,如add,remove方法操作对应的数据,array只能通过下标的方式操作
4、ArrayList被创建的时候不需要制定长度,array需要制定长度
5、ArrayList是可以添加的null,但是不建议添加null
ArrayList与vector的区别
ArrayList与vector都是基于Object[]实现的,但是ArrayList不是线程安全的,vector是线程安全的
这个可以通过vector的源码可以看出,vector类对应的方法是添加了synchronized,会保证线程是安全的
ArrayList与linkedList的区别
ArrayList底层是动态数组实现,LinkedList底层是双向链表实现。两者都是线程不安全的。
基于实现的原理,
1、ArrayList在查询数据的效率要高于LinkedList;
2、新增数据时LinkedList效率要高于ArrayList;
3、在插入或者删除数据时,受位置不同的影响时间复杂度会有不同。ArrayList在尾部添加或删除数据时,时间复杂度是O1,但是在制定的i位置插入或删除元素时,由于需要遍历数组,时间复杂度会时O(n),LinkedList在头部或尾部新增或删除元素时时间复杂度是O1,在执行i位置插入或删除数据时,由于需要遍历到指定的i位置,所以时间复杂度是O(n)。
4、内存空间方面,ArrayList是list的实现类,它的空间占用只要在尾部预留一定长度的空间;LinkedList则是需要多出空间存储前驱和后继以及数据。
HashMap和HashSet区别
HashSet底层其实是通过hashmap实现的,但是两者还是有区别的
HashMap | HashSet |
存放key-value类型数据 | 存放单元素不是key-value类型 |
通过key计算hash值 | 通过value计算hash值 |
通过put添加数据 | 通过add添加数据 |
实现Map接口 | 实现Set接口 |