一、Collection 集合框架
- 集合,或者叫容器,是一个包含多个元素的对象;
- 集合可以对数据进行存储,检索,操作;
- 它们可以把许多个体组织成一个整体:
1、工具类collections
Collections.synchronizedCollection()方法,用于集合的同步,线程安全;
实现方式:用到了23种设计模式之一的装饰模式(装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能)
返回的是一个 Collection 对象的装饰者对象 ,这个装饰者对象的所有方法都是同步的
2、HashMap:HashMap 是一个散列表,它存储的内容是键值对(key-value)映射,key只允许一个为空,value允许多个为空
HashMap底层是一个数组+链表or红黑树(java8引入,链表长度超过8转换为红黑树,小于6转换为链表),结构如图:
HashMap结构图(java8)
HashMap本身非线程安全,使用Collections.synchronizeMap(hashMap)让Hashmap变得线程安全;jdk 1.5引入 ConCurrentHashMap来解决线程安全(加锁的颗粒度更小,以每个桶为维度加锁)
3、HashSet:不允许有重复的值
HashSet 底层实现就是一个Hashmap
HashSet 存的元素就是Hashmap的key(注:添加相同key覆盖操作,所以HashSet无重复的值),HashSet 的add()方法就是Hashmap的put()方法,Hashmap的value为new Object()
4、ArrayList 用数组实现
ArrayList的默认容量大小是10;
不同于Vector,ArrayList不是线程安全的,可以使用CopyOnWriteArrayList(并发包)来代替;
当ArrayList容量不足的时候会自动进行扩容,扩容为当前大小的1.5倍
源码中的注意事项:
trimToSize():这个方法是用于将当前数组的大小修剪为当前实际元素的个数大小,什么意思呢? 就是当数组大小不足以存放当前元素的时候,我们是通过1.5的方式增大数组大小的,但是有时候这样做会导致数组实际大小远远大于实际元素个数的情况,而trimToSize方法就是用于将当前数组的大小修剪成当前元素个数的,这样的话减少了数组空间的浪费
的clear()方法也需要注意一点的就是,执行该方法之后只会将数组元素删除同时将数组元素个数置位0,但是数组大小是不会发生变化的,可以这么理解,扩容后的数组大小不变,因为后面可能还要用,如果不用了的话,可以执行trimToSize方法将数组大小也置位为0
需要注意的是ArrayList里面有一个叫modCount的变量,这个变量比较关键,他在ArrayList的结构或者内容发生变化的时候都会加1(add()、remove()、clear() 方法),而正是因为modCount的变化,所以在多线程环境下会导致我们经常遇到的一个异常的发生:ConcurrentModificationException
5、LinkedList 用双向链表实现
因为LinkedList是采用双向链表实现的,那么他自然适合于顺序访问,但是对随机访问效率不是很高;
和ArrayList一样,LinkedList也不能用于多线程环境中,原因和ArrayList是一样的,在此情况下,我们可以用ConcurrentLinkedQueue来替代LinkedList;
LinkedList是采用链表实现的,所以理论上他的长度是不受限制的;
6、ArrayList 和 LinkedList 对比
ArrayList适用于随机访问,LinkedList适用于顺序访问;
LinkedList更加适用于插入、删除大量元素的情形;
两者都是线程不安全的,如果需要线程安全版本,ArrayList对应的是CopyOnWriteArrayList,LinkedList对应的是ConcurrentLinkedQueue;
ArrayList的主要控件开销在需要在List列表的结尾预留一定的空间,而LinkedList的控件开销在于需要存储结点信息以及结点指针信息;