1、ArrayList
//初始化一个空数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//添加元素
public boolean add(E e) {
//设置容量
ensureCapacityInternal(size + 1); // Increments modCount!!
//当前数组大小+1,并设置值
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//判断数组为空设置初始化大小为 DEFAULT_CAPACITY = 10;
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//真正的设置容量的方法
grow(minCapacity);
}
private void grow(int minCapacity) {
//判断当前数组容量,如果不够则按一定的规则设置新的长度
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//拷贝老的数组到新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
可见底层实现就是数组,通过改变数组长度来实现可变数组
2、LinkedList
//链表添加元素
public boolean add(E e) {
linkLast(e);
return true;
}
//链尾添加元素
void linkLast(E e) {
//链表最后一个元素
final Node l = last;
//新建一个链表元素,设置上一个元素为l,下一个元素是null
final Node newNode = new Node<>(l, e, null);
//设置链表的最后一个元素为新建的元素
last = newNode;
//如果上一个元素为空则当前元素为第一个元素
if (l == null)
first = newNode;
//否则设置上一个节点的下一个元素是当前元素
else
l.next = newNode;
//链表大小加1
size++;
modCount++;
}
private static class Node {
//链表存储的数据
E item;
//链表下一个元素的引用
Node next;
//链表上一个元素的引用
Node prev;
Node(Node prev, E element, Node next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
底层实现就是一个双向链表结构
3、HashMap
public V put(K key, V value) {
//hash(key) 计算key的hash值
return putVal(hash(key), key, value, false, true);
}
//根据hashCode方法计算
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//定义单向链表结构数组
Node[] tab; Node p; int n, i;
//如果单向链表=null则调用resize方法
if ((tab = table) == null || (n = tab.length) == 0)
//重置链表数组
n = (tab = resize()).length;
//如果在链表结构的数组上不存在当前hash值对应的值,则直接创建新的链表节点存放在(n - 1) & hash的位置
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
//如果hash值对应的数组位置有值作如下处理
else {
Node e; K k;
//判断hash值相等并且(地址相等或者equals方法相等),hash值相等并且equals比较也想等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
else {
//遍历单向链表
for (int binCount = 0; ; ++binCount) {
//获取链表下一个元素 如果到链表末尾
if ((e = p.next) == null) {
//则创建新的元素追加到链表末尾
p.next = newNode(hash, key, value, null);
//如果binCount操作tree结构的阈值>=8-1则初始化树
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//链表当前元素hash值和equals值相等,则直接跳出循环
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//如果在链表找到hash值和equals值相等则重新设置当前元素值
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
底层实现是一个可变数组,每一个数组存储是一个链表结构数据,通过hash值来决定元素存放位置
4、HashSet
public boolean add(E e) {
//map的结构HashMap,PRESENT = new Object()
return map.put(e, PRESENT)==null;
}
可见HashSet的实现就是Value= new Object()的HashMap
5、HashTable
//有synchronized关键字说明是线程安全的
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
//通过hash值查找元素
Entry entry = (Entry)tab[index];
//如果找到元素并遍历查找当前位置链表结构下是否存在hash值相等并且equals也想等,
//如果找到则设置新值后返回旧值
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
//添加新元素
addEntry(hash, key, value, index);
return null;
}
private void addEntry(int hash, K key, V value, int index) {
modCount++;
Entry,?> tab[] = table;
if (count >= threshold) {
//重置数组,并且拷贝旧的数组到新数组
rehash();
tab = table;
hash = key.hashCode();
index = (hash & 0x7FFFFFFF) % tab.length;
}
@SuppressWarnings("unchecked")
Entry e = (Entry) tab[index];
// 创建新键值对之后在链表头添加当前元素(设置当前元素的下个节点为当前位置元素),并设置到当前位置
tab[index] = new Entry<>(hash, key, value, e);
count++;
}