java中的集合总共分为两大类,单列集合collection和双列集合map,常用的,单列集合list、set。
单列集合:
list集合:元素可重复,有序。list集合的子类有ArrayList和LinkedList,ArrayList底层是数组,查询快,增删慢,数组中的空间都是连续的,查询快是因为数组有索引,可以通过索引来直接访问,增加和删除速度快是因为添加或者删除都需要移动元素,就比如数据(1,2,3,5)我们想删除2,那么3、5元素都需要向前移动,LinkedList底层是链表,查询慢,增删快,链表是不连续的空间,查询慢是因为即使我们知道元素在哪也只能遍历链表才能找到,通过指针指向,增删快我们可以直接改变头尾指针指向的结点即可,不需要移动元素,链表里有两块区域(数据区和下一个结点的地址),也就是说不是按照顺序存放,当添加一个元素时,直接改变指针域的地址即可
set集合:元素不可重复,无序。set的子类有HashSet和TreeSet,HashSet其实就是一个HashMap,当我们new HashSet对象时,也就相当于new了一个HashMap,存放数据时,将我们存放的元素当作键来放在map中,TreeSet底层是TreeMap,底层是是红黑树
双列集合:
map子类有HashMap和TreeMap,HashMap基于hash表实现的,在jdk1.8之后底层是通过数组+链表+红黑树来实现的,在创建HashMap之前会先创建一个数组,默认长度为16,map集合是根据键值对来存储的,根据key的hash值%数组长度,得到的数据一定在长度之内,那么根据算出来的数据存在对应的位置,如果该位置为空则存入,否则去遍历链表看key是否一致,一致则视为同一个数据,覆盖,不同则将生成一个链表挂在数组的下面,但是链表的查询效率是比较低的,如果每次存都要通过链表遍历的话效率慢,自此引入了红黑树的概念,就是当链表的长度超过8位之后,就会自动将链表转换成红黑树,左边存放的是比根节点小的数字,右边存放比根节点打的数字,如果每次存放的数据都比根节点小或都比根节点大的话,都挂在左边或右边,这样又形成了链表的结构,所以引入了平衡二叉树,那么如果我们要存放的数据很多的话,也引入了扩容机制,当前长度*加载因子=……
就比如默认长度16*加载因子默认0.75=12,那么当存放第12个数据时,就会触发扩容机制,扩容为原来长度的两倍,也就是32个,是重新生成了一个数组而不是在之前的16之后加了,并把原来的数据拷贝过去,
TreeMap:基于红黑树实现的,默认是根据键来进行升序排序的,底层由红黑树构成,键不能重复,允许null值和null键
以上所有集合线程都是不安全的,要想满足线程安全可以使用Vector和ConCurrentHashMap
那么什么是线程安全呢,所谓线程安全就是内存安全,如果有多个线程共享一块区域那么一定会存在安全问题,我们可以使用加锁的方式来处理线程不安全问题,也就是说AB共享同一个时,当A在未完成自己的操作时B不能抢占资源,要等A线程处理完自己的会进行锁的释放,这时B才能来修改数据。1、悲观锁:该线程总认为会有别的线程回来抢占资源,先进行加锁 2、乐观锁:见名知意,认为不会有线程抢占资源,等去操作时先判断是否被更改,如果被更改则进行加锁。