集合框架略读

ArrayList
就是一个数组
ArrayList底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找也就是get的时候非常快
ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已
插入元素,删除元素, 会全部复制
因此,ArrayList比较适合顺序添加、随机访问的场景。
ArrayList transient Object[] elementData; 继承Serializable 但又不让elementData 序列化
因为有可能elementData没装满的话,会浪费 所以

private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out array length
s.writeInt(elementData.length);
// Write out all elements in the proper order.
for (int i=0; i<size; i++)
s.writeObject(elementData[i]);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}


每次序列化的时候调用这个方法,先调用defaultWriteObject()方法序列化ArrayList中的非transient元素,elementData不去序列化它,然后遍历elementData,只序列化那些有的元素
ArrayList和Vector的区别
Vector 线程安全的 Collections.synchronizedList(list)
LinkList
就是一个双向链表 Node(item, first,next) 删除插入就是断开重连很快,
LinkList 和 ArrayList 对比 ArrayList add快 查找速度 LinkeList 寻找慢 添加快

CopyOnWriteArrayList 是concurrent下的类 线程安全的 任何可变的操作(add、set、remove等等)都是伴随复制这个动作的
set 时加了锁 并且操作的是volatile 可见不可改 CopyOnWriteArrayList适用于读操作远多于修改操作的并发场景中。

Hash'Map
内部存的是Node hash值相同值不同时,就串在后面
HashMap的table为什么是transient的 计算hashcode调用底层系统,所以每个机器计算不同
为了避免这一点,Java采取了重写自己序列化table的方法,在writeObject选择将key和value追加到序列化的文件最后面

private void writeObject(java.io.ObjectOutputStream s)throws IOException {
  int buckets = capacity();
// Write out the threshold, loadfactor, and any hidden stuff
  s.defaultWriteObject();
  s.writeInt(buckets);
  s.writeInt(size);
  internalWriteEntries(s);
}
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
  Node<K,V>[] tab;
  if (size > 0 && (tab = table) != null) {
    for (int i = 0; i < tab.length; ++i) {
      for (Node<K,V> e = tab[i]; e != null; e = e.next) {
        s.writeObject(e.key);
        s.writeObject(e.value);
        }
     }
  }
}


ConcurrentHashMap HashMap和Hashtable的区别 Hashtable 枷锁了 底层存的Entry 不能空value

LinkedHashMap 继承自HashMap put 模板方法 实现了 afterNodeAccess 有序的
桶上分配照样 但是每个会按照Linklist 存入前后地址
每次访问一个元素(get或put),被访问的元素都被提到最后面去了
LRU (LRU即Least Recently Used,最近最少使用)  LRUCache实现缓存LRU功能都是源自LinkedHashMap的。accessOrder afterNodeAccess 

  static final class Cache {
        private LinkedHashMap<String, CacheEntry> cache;
        private Type type;

        enum Type {Positive, Negative};
    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }

accessOrder  默认是false

(1)false,所有的Entry按照插入的顺序排列

(2)true,所有的Entry按照访问的顺序排列

  第二点的意思就是,如果有1 2 3这3个Entry,那么访问了1,就把1移到尾部去,即2 3 1。每次访问都把访问的那个数据移到双向队列的尾部去,那么每次要淘汰数据的时候,双向队列最头的那个数据不就是最不常访问的那个数据了吗?换句话说,双向链表最头的那个数据就是要淘汰的数据。

  public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)  // true
            afterNodeAccess(e);
        return e.value;
    }
    void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
        if (accessOrder && (last = tail) != e) {
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a != null)
                a.before = b;
            else
                last = b;
            if (last == null)
                head = p;
            else {
                p.before = last;
                last.after = p;
            }
            tail = p;
            ++modCount;
        }
    }
afterNodeAccess
原文地址:https://www.cnblogs.com/mxz1994/p/9332269.html