集合类
List
ArrayList底层是数组,LinkedList底层是链表。数组遍历速度快,LinkedList增删元素快。
在工作中一般就用ArrayList,而不用LinkedList,原因也很简单:
-
在工作中,遍历的需求比增删多,即便是增加元素往往也只是从尾部插入元素,而ArrayList在尾部插入元素也是O(1)
-
ArrayList增删没有想象中慢,ArrayList的增删底层调用的
copyOf()
被优化过,加上现代CPU对内存可以块操作,普通大小的ArrayList增删比LinkedList更快。
List集合常用的子类有三个:
-
ArrayList,底层数据结构是数组。线程不安全
-
ArrayList是基于动态数组实现的,在增删时候,需要数组的拷贝复制。
-
ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
-
删除元素时不会减少容量,若希望减少容量则调用trimToSize()
-
它不是线程安全的。它能存放null值。
-
-
LinkedList,底层数据结构是链表。线程不安全
-
底层实现是双向链表[双向链表方便实现往前遍历]
-
-
Vector,底层数据结构是数组。线程安全,方法带有synchronized
-
底层是数组,现在已少用,被ArrayList替代,原因有两个:
-
Vector所有方法都是同步,有性能损失。
-
Vector初始length是10 超过length时 以100%比率增长,相比于ArrayList更多消耗内存。
-
Set
Set常用子类:
-
HashSet集合,底层数据结构是哈希表(是一个元素为链表的数组)
-
TreeSet集合,底层数据结构是红黑树(是一个自平衡的二叉树),保证元素的排序方式
-
LinkedHashSet集合,底层数据结构由哈希表和链表组成。
Map
散列表
散列表为每个对象计算出一个整数,称为散列码。根据这些计算出来的整数(散列码)保存在对应的位置上!在Java中,散列表用的是链表数组实现的,每个列表称之为桶
一个桶上可能会遇到被占用的情况(hashCode散列码相同,就存储在同一个位置上),这种情况是无法避免的,这种现象称之为:散列冲突
-
此时需要用该对象与桶上的对象进行比较,看看该对象是否存在桶子上了~如果存在,就不添加了,如果不存在则添加到桶子上
-
当然了,如果hashcode函数设计得足够好,桶的数目也足够,这种比较是很少的~
-
在JDK1.8中,桶满时会从链表变成平衡二叉树
红黑树
红黑树用的是是两种方式来实现节点交换操作:
-
旋转:顺时针旋转和逆时针旋转
-
反色:交换红黑的颜色
红黑树为了保持平衡,还有制定一些约束,遵守这些约束的才能叫做红黑树:
-
红黑树是二叉搜索树。
-
根节点是黑色。
-
每个叶子节点都是黑色的空节点(NIL节点)。
-
每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
-
从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点(每一条树链上的黑色节点数量(称之为“黑高”)必须相等)。
HashMap和HashTable
从存储结构和实现来讲基本上都是相同的。它和HashMap的最大的不同是它是线程安全的,另外它不允许key和value为null。Hashtable是个过时的集合类,不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换
Queue队列
生产者和消费者模式,最简单的方式就是用阻塞队列去写