一、ArrayList源码解读
- 实现原理,内部由一个数组构成。关键属性:数组-容量、元素个数、修改编号(fast-fail机制)
- 初始化是一个空数组,默认容量为10,扩容机制是新增加当前容量的一半,如果扩容后的值小于最小容量(size+addAll.size).
- fast-fail机制:快速失效系统一种可以立即报告任何可能表明故障的情况的系统.(modCount属性),新增和删除都会增加modCount,修改数组中的对象modCount不会修改。
- 迭代器:实现是通过游标来控制,获取数据还是原来的数组,容器实现Iterator接口的提供同样的访问方式,这就是迭代器模式的实现。
二、LinkList 源码解读
- 实现原理:内部有一个头结点和尾结点,结点内部结构是由结点对象、上一个结点、下一个结点组成。
public class LinkedList<E>{
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
/**
* 结点数据结构
*/
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
}
- 实现双向链表功能
- 因为是链式存储,无需扩容。
- 迭代器:同样实现
三、ArrayList与LinkedList的实现和区别
- 实现方式、应用场景、扩容方式、大小对比情况
| 类 |
实现方式 |
应用场景 |
扩容方式 |
最大长度 |
| ArrayList |
动态数组 |
读取 |
1.5倍 |
2^32-8 |
| LinkedList |
链表 |
插入、删除 |
正常插入末尾 |
无限大 |
- 时间复杂度对比
| 类 |
读取 |
插入删除 |
| ArrayList |
O(1):根据下表读取 |
O(n):插入或删除需要将之后的所有元素后移或迁移 |
| LinkedList |
O(n):循环遍历 |
O(1):只需要制定的结点进行插入或删除 |
四、HashMap、Hashtable、ConcurrentHashMap
- HashMap的key和value可以为null,Hashtable、ConcurrentHashMap的key和value不能为空,为什么jdk要这样设计呢?
ConcurrentHashmap和Hashtable都是支持并发的,这样会有一个问题,当你通过get(k)获取对应的value时,如果获取到的是null时,你无法判断,它是put(k,v)的时候value为null,还是这个key从来没有做过映射。HashMap是非并发的,可以通过contains(key)来做这个判断。而支持并发的Map在调用m.contains(key)和m.get(key),m可能已经不同了。