zoukankan      html  css  js  c++  java
  • 集合框架略读

    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
  • 相关阅读:
    《Scrum实战》第4次课【全职的Scrum Master】作业汇总
    回顾Scrum学习:《Scrum实战》第4次课【全职的Scrum Master】作业
    孙式无极桩站桩要领--林泰年
    [Android Tips] 29. 如何判断当前编译的是哪个 Flavor ?
    [Jenkins] 解决 Gradle 编译包含 SVG Drawable 出现异常
    [Android Tips] 28. 如何指定运行特定的 Android Instrumentation Test
    [Gradle] 给已存在的 task 添加依赖
    [Gradle] 针对不同的项目类型应用不同的 findbugs 配置
    [Android Tips] 27. 检查 APK 是否可调试
    [Gradle] 如何强制 Gradle 重新下载项目的依赖库
  • 原文地址:https://www.cnblogs.com/mxz1994/p/9332269.html
Copyright © 2011-2022 走看看