JDK源代码阅读笔记(一)------容器篇

来源:互联网 发布:seo www.urkeji.com 编辑:程序博客网 时间:2024/05/17 08:17
一、类图


二、基本抽象基类
1.Collection
所有List和Set都需要实现的基本接口

2.AbstractCollection
此类提供 Collection 接口的骨干实现,以最大限度地减少了实现此接口所需的工作
用迭代器对数据进行访问(不是随机访问)

3.AbstractList
此类提供 List 接口的骨干实现,以最大限度地减少实现“随机访问”数据存储(如数组)支持的该接口所需的工作
用迭代器对数据进行访问(不是随机访问)

4.AbstractSet
此类提供 Set 接口的骨干实现,从而最大限度地减少了实现此接口所需的工作
用迭代器对数据进行访问(不是随机访问)

5.AbstractSequentialList
此类提供了 List 接口的骨干实现,从而最大限度地减少了实现受“连续访问”数据存储(如链接列表)支持的此接口所需的工作(用迭代器对数据进行访问,不是随机访问)

6.AbstractSet
此类提供 Set 接口的骨干实现,从而最大限度地减少了实现此接口所需的工作。
用迭代器对数据进行访问,不是随机访问)

7.AbstractMap
此类提供 Map 接口的骨干实现,以最大限度地减少实现此接口所需的工作
用迭代器对数据进行访问,不是随机访问)


三、List

List可以将元素维护在特定的序列中,并且允许一个相同元素在集合中多次出现。List接口在Collection接口的基础上增加了大量的方法,使得可以在List中间插入和移除元素。

Abstract类之外,在学习中比较常用的类有ArrayList(基于数组实现),LinkedList(基于循环链表实现)Vector(基于数组实现,线程安全),Stack(是Vector的子类,基于数组实现)

1.ArrayList
继承自AbstractList,实现List等接口,基本属性如下:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer.
     */
    private transient Object[] elementData;

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;‘
}

基本数据存在名为elementData的数组中,查询指定元素和遍历整个元素都是对数组进行操作
对于ArrayList的增加与删除,利用了Arrays工具类进行数组复制,Arrays的最终实现是利用如下语句

System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));

该语句会编译成本地代码,提高效率

2.Vector
实现大体和ArrayList一样,只是每个方法上加了同步标志

3.Stack
继承于Vector,一个栈,限制客户端代码操作数组的位置,只能在栈顶,具体实现时即是数组最后一个元素的位置

4.LinkedList
继承自AbstractSequentialList(用迭代器对数据进行访问,不是随机访问)
实现的是一个双链表,所有操作都是按照双重链接列表的需要执行的,基本属性如下:

public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    private transient Entry<E> header = new Entry<E>(null, null, null);
    private transient int size = 0;

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
        header.next = header.previous = header;
    }
}

header为头节点,size记录链表长度

其中Entry<E>是一个内部类,作为链表的一个节点:
private static class Entry<E> {
      E element;
      Entry<E> next;
      Entry<E> previous;

      Entry(E element, Entry<E> next, Entry<E> previous) {
          this.element = element;
          this.next = next;
          this.previous = previous;
      }
    }

虽然LinkedList获取指定位置的元素时较ArrayList按索引获取较慢,但是JDK中对get方法做了优化:
private Entry<E> entry(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException("Index: "+ index + ", Size: "+size);

        Entry<E> e = header;
        if (index < (size >> 1)) {
            for (int i = 0; i <= index; i++)
                e = e.next;
        } else {
            for (int i = size; i > index; i--)
                e = e.previous;
        }
        return e;
    }


四、Set
包括HashSet(无序不重复),LinkedHashSet(按放入顺序有序不重复),TreeSet(按红黑树方式有序不重复)

1.HashSet
利用hash值来查找容器类的元素,因为容器中没个元素的值不相同,所以可以根据元素值来生成hash码

其基本属性如下:

public class HashSet<E> extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();
}

map中的键值“E”用来存储HasgSet中元素值,对应的“Object”固定用PRESENT来表示

其实现基础就是HashMap,所以,HashSet不像List那样可以“随机”访问,只能用迭代器访问

2.TreeSet

其实现基础就是TreeMap,其基本属性如下:

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
    /**
     * The backing map.
     */
    private transient NavigableMap<E,Object> m;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();
}

3.LinkedHashSet
继承于HashSet,其基本属性如下:

public class LinkedHashSet<E> extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2851667679971038690L;
}


五、Map

包括HashMap(key无序不重复),LinkedHashMap(key按放入顺序有序不重复),TreeMap(key按红黑树方式有序不重复)

1.HashMap
利用每个key值生成散列值,根据散列值进行数据查找
下图是使用链表来解决散列过程中的碰撞问题,新元素插入链表头


在HashSet中有个loadFactor(负载因子),对于上图所示总共有11个位置,目前有4个位置已经存放,即40%的空间已被使用。在HashSet的默认实现中,初始容量为16,负载因子为0.75,也就是说当有75%的空间已被使用,将会进行一次再散列(再哈希),之前的散列表(数组)将被删除,新增加的散列表是之前散列表长度的2倍,最大值为Integer.MAX_VALUE。

其基本属性如下:

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
{

    /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
    transient Entry[] table;

    /**
     * The number of key-value mappings contained in this map.
     */
    transient int size;

    /**
     * The next size value at which to resize (capacity * load factor).
     * @serial
     */
    int threshold;

    /**
     * The load factor for the hash table.
     *
     * @serial
     */
    final float loadFactor;
}

其中Entry[] table是用来存放value的数组,数组下标根据key的散列值生成,Entry的基本实现如下:

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        final int hash;
}

其中 “Entry<K,V> next” 保存为该的下一个节点
每次查找先找到table中的一个节点,然后以该节点作为头节点进行链表的遍历

2.TreeMap
key按红黑树方式有序的放入TreeMap,其基本属性如下:

public class TreeMap<K,V> extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
    /**
     * The comparator used to maintain order in this tree map, or
     * null if it uses the natural ordering of its keys.
     *
     * @serial
     */
    private final Comparator<? super K> comparator;

    private transient Entry<K,V> root = null;

    /**
     * The number of entries in the tree
     */
    private transient int size = 0;
}

其中comparator用来比较key值的大小,root作为整棵树的根节点,Entry为每个节点,其属性如下:

    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left = null;
        Entry<K,V> right = null;
        Entry<K,V> parent;
        boolean color = BLACK;
}

3.LinkedHashMap

继承与HashMap,新加入一个元素时,需要维护hash表和双链表这两个表,以保证既能利用hash来快速查找数据,又能按map中输入数据的顺序输出数据,如果在映射中重新插入 键,则插入顺序不受影响,基本属性如下:

public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
{
    private static final long serialVersionUID = 3801124242820219131L;

    /**
     * The head of the doubly linked list.
     */
    private transient Entry<K,V> header;

    /**
     * The iteration ordering method for this linked hash map: 
      <tt>true</tt> for access-order,
     *  <tt>false</tt> for insertion-order.
     * @serial
     */
    private final boolean accessOrder;
}

其中header代表双链表的头节点,accessOrder用来选择输出的顺序

原创粉丝点击