JavaSE知识点总结:java集合篇

1、List集合

List继承了Collection,是有序的列表.
主要实现类有ArrayList、LinkedList、Vector、Stack等

ArrayList

  • 数组队列,非线程安全。被始化为Object[],查询修改快、增加删除慢,允许null值
  • 动态扩容,初始10,扩容size的1.5倍 newCapacity = size + (size >> 1),阈值Integer.MAX_VALUE
  • 删除会发生数据元素的移动,通过System.arraycopy数据拷贝实现
  • modCount:迭代器通过modCount的值保持一致
  • transient :表示序列化时被忽视。elementData扩容的过程中是可变的,ArrayList才会在elementData属性前加上transient修饰符,序列化是通过流的方式实现ArrayList的writeObject()、readObject():

LinkedList

  • 链表实现(1.8单向链表),非线程安全
  • 查询更新慢、增加删除快(查询采为2分法迭代)
Node<E> node(int index) {
    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}

Vector

  • 数组实现、线程安全的。synchronized方式实现的线程安全数组
  • 动态扩容,初始10。扩容是1倍。空构造会初始化一个容量为10的数组,不像ArrayList是空的不可变数组。

Stack

  • 基于数组实现的栈,线程安全它继承与Vector,特性是FILO(先进后出)
  • Stack也是通过数组实现的,而非链表

CopyOnWriteArrayList

  • concurrent并发包中ArrayList线程安全的新实现方式
  • Lock方式实现的线程安全。

2、Set集合

继承了Collection,值无序不可重复。 主要实现类有
HashSet、Hashtable、TreeSet、LinkedHashSet等

HashSet

  • 通过HashMap Key的特性实现的不可重复的无序集合。允许null值
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
    map = new HashMap<>();
}
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

TreeSet

  • TreeSet也是基于TreeMap来实现有序不可重的集合;允许插入Null值;非线程安全;
  • 自然排序、自定义排序,默认是自然排序;
  • 底层使用红黑树结构,而不是哈希表结构;
  • TreeSet实现NavigableSet接口使得TreeSet具备了元素搜索功能;

LinkedHashSet

  • LinkedHashSet也是基本LinkedHashMap实现的有序不可重复的集合、非线程安全
  • 数据结构是链表和哈希表,元素有序唯一

CopyOnWriteArraySet

  • concurrent并发包中set线程安全类
  • CopyOnWriteArraySet是通过CopyOnWriteArrayList 实现,插入元素先判断是否存在
  • Lock方式实现的线程安全。
/**
 * Appends the element, if not present.
 *
 * @param e element to be added to this list, if absent
 * @return {@code true} if the element was added
 */
public boolean addIfAbsent(E e) {
    Object[] snapshot = getArray();
    return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
        addIfAbsent(e, snapshot);
}

3、Map集合

Map 是不同于Collection的一种键-值对(key-value)集合,
主要实现类有HashMap、LinkedHashMap、TreeMap、HashTable等。

HashMap

  • HashMap由数组+链表实现的key-value键值对集合,无序不可重复、非线程安全
// Hash表初始容量 16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 
//数组最大容量 1073741824
static final int MAXIMUM_CAPACITY = 1 << 30; 
//默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;  //key hashCode取模运算后在数组中对应的index下标
    final K key;     //数据的key
    V value;         //数据的value
    Node<K,V> next;  //指向下一个节点
}
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//put方法懒加载实现
if ((tab = table) == null || (n = tab.length) == 0)
      n = (tab = resize()).length;
  • 单向链表,最后一个链表节点entry的next指向null
    并允许使用 null 值和 null 键
  • HashMap 通过 (n - 1) & hash 来决定元素的位置(n 是当前数组大小)
  • Node[] table:存储数据的哈希表;初始长度 length = 16,扩容时容量为原先的两倍(n * 2)
  • loadFactor:负载因子,确定数组长度与当前所能存储的键值对最大值的关系;
  • threshold:所能容纳的 key-value 对极限 ;threshold = length * Load factor,当存在的键值对大于该值,则进行扩容
  • 懒加载:new Hash()未初始化哈希表 Node[] table;当发现哈希表为空或者长度为 0 时,会使用 resize 方法进行初始化,这里很显然运用了 lazy-load 懒加载原则,当哈希表被首次使用时,才进行初始化。
    当链表中元素大于等于 8,这时有可能将链表改造为红黑树的数据结构,为什么我这里说可能呢?
static final int TREEIFY_THRESHOLD = 8;//默认链表元素大于等于8可被树化
static final int MIN_TREEIFY_CAPACITY = 64; //可树化的最小表容量为 64,

//putVal method
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
    treeifyBin(tab, hash);
    
final void treeifyBin(Node<K,V>[] tab, int hash) {
    int n, index; Node<K,V> e;
    //哈希表容量<64,继续扩容而不树化
    //防止哈希表容量较小,哈希碰撞的几率会比较大,导致出现长链表
    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
        resize();
    else if ((e = tab[index = (n - 1) & hash]) != null) {
        //todo 这里转化红黑树
    }
}

TreeMap

  • 红黑树的实现 一种键-值对(key-value)可排序集合,非线程安全。
  • TreeMap集合是基于红黑树(Red-Black tree)
  • NavigableMap实现
  • TreeMap保存的记录会根据 Key 排序(默认为升序排序), key 必须实现 Comparable 接口,可自定义排序。
  • TreeMap 会按照其 key 的 compareTo 方法来判断 key 是否重复
static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;
    V value;
    Entry<K,V> left;
    Entry<K,V> right;
    Entry<K,V> parent;
    boolean color = BLACK;
}

Hashtable:

  • 一个遗留类,线程安全,与 HashMap 类似
  • 当不需要线程安全时,选择 HashMap 代替
  • 当需要线程安全时,使用 ConcurrentHashMap 代替

你可能感兴趣的:(java)