JAVA集合框架主要包括5个部分
一、Collection接口
Collection接口的继承关系如下:
Collection<--List<--Vector
Collection<--List<--ArrayList
Collection<--List<--LinkedList
Collection<--Set<--HashSet
Collection<--Set<--HashSet<--LinkedHashSet
Collection<--Set<--SortedSet<--TreeSet
List的特点:保证以某种特定插入顺序来维护元素顺序,即保持插入的顺序,另外元素可以重复。
Set的特点:维持它自己的内部排序,随机访问不具有意义。另外元素不可重复。
1、Vector
Vector核心代码
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { protected Object[] elementData; /** * The number of valid components in this {@code Vector} object. * Components {@code elementData[0]} through * {@code elementData[elementCount-1]} are the actual items. * * @serial */ protected int elementCount; protected int capacityIncrement; //可以设定固定增量 }Vector底层数据结构是数组,只不过这个数组的容量可以动态扩展。基于数组查找效率高。而且从线程安全的角度来将,Vector是线程安全的。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private transient Object[] elementData; public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) //如果参数小于0,则抛出参数不合法异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } }ArrayList底层数据结构是数组,这个数组也是动态可扩展的。基于数组查找效率高。它不是线程安全的。
private transient Entry<E> header = new Entry<E>(null, null, null); 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低。它不是线程安全的。
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; // 底层使用HashMap来保存HashSet中所有元素。 private transient HashMap<E,Object> map; // 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。 private static final Object PRESENT = new Object(); /** * 默认的无参构造器,构造一个空的HashSet。 * * 实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。 */ public HashSet() { map = new HashMap<E,Object>(); } /** * 构造一个包含指定collection中的元素的新set。 * * 实际底层使用默认的加载因子0.75和足以包含指定 * collection中所有元素的初始容量来创建一个HashMap。 * @param c 其中的元素将存放在此set中的collection。 */ public HashSet(Collection<? extends E> c) { map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } }HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, java.io.Serializable { public LinkedHashSet(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor, true); } public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); } public LinkedHashSet() { super(16, .75f, true); } public LinkedHashSet(Collection<? extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); } }LinkedHashSet具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按照元素的插入次序显示。
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable { // NavigableMap对象 private transient NavigableMap<E,Object> m; // TreeSet是通过TreeMap实现的, // PRESENT是键-值对中的值。 private static final Object PRESENT = new Object(); // 不带参数的构造函数。创建一个空的TreeMap public TreeSet() { this(new TreeMap<E,Object>()); } // 将TreeMap赋值给 "NavigableMap对象m" TreeSet(NavigableMap<E,Object> m) { this.m = m; } // 带比较器的构造函数。 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<E,Object>(comparator)); } // 创建TreeSet,并将集合c中的全部元素都添加到TreeSet中 public TreeSet(Collection<? extends E> c) { this(); // 将集合c中的元素全部添加到TreeSet中 addAll(c); } // 创建TreeSet,并将s中的全部元素都添加到TreeSet中 public TreeSet(SortedSet<E> s) { this(s.comparator()); addAll(s); } }TreeSet基于TreeMap,生成一个总是处于排序状态的set,它实现了SortedSet接口,内部以TreeMap来实现
/** * The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry[] table; static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; }HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
static int indexFor(int h, int length) { return h & (length-1); }
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> { /** * The head of the doubly linked list. * 双向链表的头节点 */ private transient Entry<K,V> header; /** * The iteration ordering method for this linked hash map: true * for access-order, false for insertion-order. * true表示最近最少使用次序,false表示插入顺序 */ private final boolean accessOrder; }LinkedHashMap继承自HashMap,同时自身有一个链表,使用链表存储数据,不存在冲突。
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> { // 存储数据的Entry数组,长度是2的幂。 // WeakHashMap是采用拉链法实现的,每一个Entry本质上是一个单向链表 private Entry[] table; // queue保存的是“已被GC清除”的“弱引用的键”。 // 弱引用和ReferenceQueue 是联合使用的:如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中 private final ReferenceQueue<K> queue = new ReferenceQueue<K>(); }WeakHashMap 继承于AbstractMap,实现了Map接口。和HashMap一样,WeakHashMap 也是一个散列表,它存储的内容也是键值对(key-value)映射,而且键和值都可以是null。不过WeakHashMap的键是“弱键”。在 WeakHashMap 中,当某个键不再正常使用时,会被从WeakHashMap中被自动移除。
和HashMap一样,WeakHashMap是不同步的。可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap。
4、HashTable
HashTable核心代码
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable { // Hashtable保存key-value的数组。 // Hashtable是采用拉链法实现的,每一个Entry本质上是一个单向链表 private transient Entry[] table; // Hashtable中元素的实际数量 private transient int count; }和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable { // 用于保持顺序的比较器,如果为空的话使用自然顺保持Key的顺序 private final Comparator<? super K> comparator; // 根节点 private transient Entry<K,V> root = null; // 树中的节点数量 private transient int size = 0; // 多次在集合类中提到了,用于举了结构行的改变次数 private transient int modCount = 0; } 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; /** * 根据给定的键、值、父节点构造一个节点,颜色为默认的黑色 */ Entry(K key, V value, Entry<K,V> parent) { this.key = key; this.value = value; this.parent = parent; } // 获取节点的key public K getKey() { return key; } // 获取节点的value public V getValue() { return value; } /** * 修改并返回当前节点的value */ public V setValue(V value) { V oldValue = this.value; this.value = value; return oldValue; } // 判断节点相等的方法(两个节点为同一类型且key值和value值都相等时两个节点相等) public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>)o; return valEquals(key,e.getKey()) && valEquals(value,e.getValue()); } // 节点的哈希值计算方法 public int hashCode() { int keyHash = (key==null ? 0 : key.hashCode()); int valueHash = (value==null ? 0 : value.hashCode()); return keyHash ^ valueHash; } public String toString() { return key + "=" + value; } }TreeMap基于红黑树(点击查看树、红黑树相关内容)实现。查看“键”或“键值对”时,它们会被排序(次序由Comparable或Comparator决定)。