Java-容器

158 阅读4分钟

记录

日期说明
2023/1/1首次创建
2023/2/18更新hashMap

总纲

关于容器的一些概念

List

有序、可重复,删除、插入效率低,查询效率高

  1. ArrayList:线程不安全。数组存储,非同步,支持RandomAcess(高效随机访问)。
  • grow方法扩容。初始10,加载因子1,扩容*1.5+1
  1. LinkedList:线程不安全。双向链表存储,允许有null,非同步
  2. listIterrator:线程不安全。特殊的Iterator迭代器,允许遍历时插入,删除,双向访问等
  3. vector:线程安全。数组存储,效率低,不推荐使用。
  4. CopyOnWriteArrayList:线程安全。对写加锁,通过volatile保证可见性
  5. ConcurrentLinkedQueue:线程安全。
  6. SynchronizedList:线程安全。

Set

无序,不重复,删除、插入效率高,查询效率低?

  1. HashSet:线程不安全。允许一个null,底层HashMap存储,初始16,加载因子0.75,扩容*2
  2. LinkedHashSet:底层LinkedHashMap存储。先进先出
  3. TreeSet:可以排序等,基于TreeMap进行存储
  4. SortedSet:线程不安全。底层是二叉树
  5. ConcurrentSkipListSet:线程安全。基于ConcurrentSkipLinstMap实现
  6. CopyOnWriteArraySet:线程安全。基于CopyOnWriteArrayList实现
  7. SynchronizedSet:线程安全。

Queue

先进先出

  1. LinkedBlockingQueue:线程安全。基于链表实现的可阻塞FIFO队列
  2. ArrayBlockingQueue:线程安全。基于数组实现的可阻塞的FIFO队列
  3. PriorityBlockingQueue:线程安全。按优先级排列的队列

Map

  1. HashMap:允许一个null。非同步,基于哈希散列表(数组+链表+红黑树)进行存储
  • revise方法扩容:初始16,加载因子0.75,扩容*2,最大2^30
    • 扩容时,重新计算容量,阈值,所有元素重新计算哈希值来存储,非常耗时
  • 线程不安全
    • 1.7及之前。在并发时可能造成数据不准确和内部链表死循环。原因是在扩容时修改链表,有可能形成循环
    • 1.7。扩容的方式是将所有数据重新排列,然后位置打乱,再根据hash重新计算
    • 1.8开始。修复了循环链表,但是有可能数据丢失
      • 等链表的while循环结束后才给数组赋值,因为用的局部变量链表的值,所以多线程时不影响
      • 对原来的数据下标进行了两次for循环,计算出的新下标位置只能在原下标位置或者在原下标位置叫上原容量位置
      • 参考
  • 初始化
    • HashMap()
    • HashMap(initialCapacity)
    • HashMap(initialCapacity, float loadFactor)
    • HashMap(map)
    • 指定数量会处理成2的指数作为容量,然后乘以填充因子得到阈值
  • put
    • 首先key计算hashCode,然后(高16位异或低16位)&(n-1),其中n表示当前数组长度,得到最终的数组索引。两次扰动(1.8)/9次扰动(四次位运算和五次异或运算)(1.7)。目的是为了计算结果尽可能离散
    • 然后判断索引位是为null,是就直接添加,否则插入
      • 1.7:只有链表,头插
      • 1.8开始。个数<8,尾插,个数<=6,链化。结束>=,红黑树化
  • get
    • 1.7。key为null就去数组的第一个元素;否则就计算哈希值找到对应的索引,然后遍历链表查找。
    • 1.8开始。首先判断索引上层是链表还是树(用第一个节点来判断),如果是链表就遍历;如果是树就查找
    • 不能用于判断是否有某个值。因为返回null可能值本身就是null,或者没有某个值。要用containsKey
  • 因为是散列表的数据结构,所以无论是插入、修改、查询的事件复杂度都是O(1)
  1. HashTable
    • 线程安全。但是不建议使用
    • key和value都不能为null
    • 直接使用对象的hashcode
    • 初始容量是11,扩容因子是0.75,扩容量是*2+1
  2. TreeMap:基于红黑树进行存储
  3. WeakHashMap:使用弱密钥的哈希散列表
  4. LinkedHashMap:使用元素的自然顺序进行排序,基于哈希散列表进行存储,维护头尾指针记录顺序
  5. IdentifyHashMap:?
  6. ConCurrentHashMap:线程安全。任意数量读取线程,任意数量的读取加一个写,一定数量的写线程可以并发访问
  • 1.7及之前。采用一种更加细粒度的分段锁
  • 1.8开始。使用synchronized关键字实现。
  1. ConcurrentSkipListMap:线程安全。基于线程安全的排序映射表,结合skipList结构作为内部来实现,在理论上能够在O(log(n))时间内完成查找、插入、删除操作
  2. SynchronizedMap:
  3. WeakHashMap
  • 对key实行弱引用,如果一个key不再被外部引用,那么就可以被gc回收

其他

  1. Vector:类似于ArrayList,同步,初始10,加载因子1,扩容*2
  2. Stack:后进先出
  3. HashTable:类似于HashMap,不允许null,同步,初始大小为11,扩容*2+1
  4. Properties:继承于HashTable,属性列表中的每个键及其对应的值都是字符串
  5. BitSet