• 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>
    
  • 相关阅读:
    Java 中的定时任务(一)
    超实用 Git 使用方式介绍
    TCP 建立连接为什么要握 3 次手?
    OSI、TCP、IP、UDP 这些都是啥??
    Java 中线程安全问题
    PlantUML——3.Graphviz的安装
    PlantUML——2.中文乱码及解决
    PlantUML——1.Hello
    maven实战系列
    NGUI优化之Drawcall
  • 原文地址:https://www.cnblogs.com/we9999/p/12409330.html
Copyright © 2020-2023  润新知