Java容器
Java容器
Java中容器类可以分为两大类:Collection与Map。
- Collection:存储对象的集合;
- Map:存储键值对。
Collection

Set
TreeSet
基于红黑树,支持有序性操作。
HashSet
基于哈希表实现,支持快速查找,不支持有序性操作。
LinkedHashSet
基于双向链表实现,只能顺序访问,可以快速在其中间插入和删除元素。
List
ArrayList
基于动态数组实现,支持随机访问。
ArrayList源码
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
//基于数组实现,RandomAccess表示支持随机访问。
private static final int DEFAULT_CAPACITY = 10;
//默认大小为10
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
//int newCapacity = oldCapacity + (oldCapacity >> 1); 表示每次扩容为旧容量的1.5倍。
transient Object[] elementData;
//使用transient修饰,默认数组不会被序列化。
Vector
和ArrayList相似,是线程安全的(除了私有方法,其他方法都使用了synchronized修饰)。
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }
    public synchronized void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        if (elementCount < oldCapacity) {
            elementData = Arrays.copyOf(elementData, elementCount);
        }
    }
    public synchronized int capacity() {
        return elementData.length;
    }
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
//扩容的时候看传入的参数,如果大于0就扩大为原来基础上加上你传入的参数,如果小于0就扩大为原来的两倍(实际开发中因该很少调用构造函数,所以大多数情况是扩大为原来的两倍)。
``
LinkedList
基于双向链表实现,只能顺序访问,但是可以快速在链表中间插入和删除元素。
    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;
        }
    }
//使用双向链表且每个节点存储了上下两个节点。
transient Node<E> first;
transient Node<E> last;
//每个链表存储了first和last指针
Queue
LinkedList
常用于实现双向队列
PriorityQueue
基于堆结构实现,可以实现优先队列。
Map
TreeMap
基于红黑树实现
HashMap
基于哈希表实现
在jdk1.7及以前的时候使用的是数组和链表,在jdk1.8及以后使用的是数组、链表和红黑树。
transient Entry[] table;
//不会被序列化
拉链法
HashMap<String, String> map = new HashMap<>();
map.put("K1", "V1");
map.put("K2", "V2");
map.put("K3", "V3");
- 新建一个 HashMap,默认大小为 16;
- 插入 <K1,V1> 键值对,先计算 K1 的 hashCode 为 115,使用除留余数法得到所在的桶下标 115%16=3。
- 插入 <K2,V2> 键值对,先计算 K2 的 hashCode 为 118,使用除留余数法得到所在的桶下标 118%16=6。
- 插入 <K3,V3> 键值对,先计算 K3 的 hashCode 为 118,使用除留余数法得到所在的桶下标 118%16=6,插在 <K2,V2> 前面。
注意:链表的插入是头插法的方式进行的。
查找:
- 计算键值对所在的桶;
- 在链表上顺序查找,时间复杂度显然和链表的长度成正比。
扩容的时候扩大为原来的2倍。
void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<>(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}
HashTable
与HashMap类似,是线程安全的,但不推荐使用(推荐使用ConcurrentHashMap)
LinkedHashMap
使用双向链表来维护元素的顺序,顺序插入顺序或者最近最少使用(LRU)顺序。
继承HashMap
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号