Java集合

转载https://feelschaotic.gitbook.io/android-knowledge-system/liu-ji-chu-neng-li/java-gao-ji/ji-he

集合

集合那么多,怎么掌握

  想要掌握集合,必须先知道,为什么会有集合,集合的诞生背景是什么呢?

想想如果用数组

  • 长度固定,满了需要自己copy扩容
  • 需要自己记录实际存储元素,毕竟length只拿到了array的容量
  • 只能存放同一类型
  • 数组不是面向对象

  用起来是不是不那么顺手?集合就是在这种情况下应运而生。

不同的集合要解决的问题不一样,这么多类,别死记硬背,根据场景+类前后缀来区别。

  • 想要映射关系?一律找Map后缀,映射关系的元素需不需要有序?有序是怎么个有序法?按插入顺序还是访问顺序?那我们可以在Map分类下找LinkedHashMap或TreeMap.
  • 只存Value又要有序?使用List集合容器!
  • 去重?使用Set集合!想要去重又有序TreeSet

  集合是为数据和业务服务的,对外就是增、删、改、查,对内包含初始化、数据的维护、动态扩容等等细节.在学习集合时,我们应该保持一个清晰的主线

只关注几个重要的问题:

  1. 它解决了什么数据问题?
  2. 它如何解决这些问题?
  3. 为了解决这些问题,引入了什么新的问题,它是如何平衡的?

  程序的世界里,没有银弹,否则其他集合就没有了存在的必要。也就是说每个集合一定有不同的侧重点,它在时间和空间上,一定是有所取舍,有所平衡,在这个目标下,做出最合适的优化实现。

20210831162012

HashMap

关键词
  • 共同:二次Hash2倍扩容Fail-Fast机制链地址法解决冲突Key尽量是不可变对象容量必须是2的n次方

  • Java7:数组+链表、链表头插(ReHash并发链表环)

  • Java8:数组+链表+红黑树、链表尾插

前言

  HashMap并不简单,涉及的知识遍及线程、Java内存模型、哈希计算、链表结构、二进制操作等等,所以一个HashMap的掌握程度也能看出开发的技术功能。

  那怎么学?我建议是细节吃透+发散思维

  1. 咬死细节,多问几个为什么。 跟着下面几篇博文,先对HashMap的整体流程有所熟悉,再死扣设计细节。比如为什么要数组+链表这个结构?换成为什么要二次哈希?为什么String的hash算法使用固定常量31?为什么JDK1.8后使用红黑树代替过长的单链表?……
  2. 发散思维,多想还有什么用途。 不满足于掌握HashMap,而是要吃透知识点,那,既然涉及到哈希计算,我们平时常用的哈希算法有哪些?又有哪些应用?既然有多线程问题,那HashTable和CurrentHashMap是怎么解决的?有什么不同?既然有红黑树,红黑树在哪些地方还有应用?……

这些问题,相信阅读完下面几篇优秀的博文,你就会得到答案。

博文

  • 图解HashMap原理

    就着配图,HashMap的源码读起来非常轻松,本文基于JDK1.7源码,非常细致地剥完了HashMap的原理。

  • HashMap深度分析

    从面试的角度切入,可以作为细节点的补充。

细节

LinkedHashMap

前言

  一谈到 LRU 就离不开 LinkedHashMap,你想想,有哪个数据结构,既有 O(1) 的取值复杂度(不冲突的情况下),又能有序。 摸清楚 LinkedHashMap你也可以自己设计一个淘汰自策略的LRU容器了

  由于 LinkedHashMap 继承自 HashMap,所以在分析源码之前一定要先看看 HashMap 的源码

顺便说一句,LinkedHashMap 利用了 Hook 方法,使得自己实现有序机制的同时又能最大程度复用 HashMap 原有的流程,是模板模式的绝佳应用

博文

  • 图解LinkedHashMap原理

    通俗易懂,一篇你就能搞懂 LinkedHashMap 的原理,美中不足是本文基于 jdk1.7。

HashTable

ConcurrentHashMap

  总体来说,许多人对于ConcurrentHashMap的印象,停留在以分段锁减轻免竞争条件的并发实现,这不足以完全说明其优势。

  回到并发编程领域,提高并发效率可从几方面入手: img

  1. 减少临界区区域:这是容易理解的,在并发中,临界区是依次通过的,即临界区是串行的。
  2. 加速通过临界区:使临界区内的逻辑代码执行得尽可能地快,这样,线程在临界区内停留的时间更短。
  3. 减少竞争条件:通过去除不必要的竞争条件,或竞争不同的临界区,来减少线程间的相互影响。

  ConcurrentHashMap对于并发效率的优化,也将从这几方面入手。

博文

  • 图解ConcurrentHashMap

    从普遍的角度(源码和对外API)一一来解析 ConcurrentHashMap 的原理。

  • 见识不一样的ConcurrentHashMap

    换了另一个切入点 —— 从优化的角度来解析 ConcurrentHashMap,到底 ConcurrentHashMap 在实现并发安全的基础上如何一步步优化以更好地支持高并发呢?且看本文。

TreeMap

  提起红黑树大家都不陌生,提起 TreeMap 却少有人了解,TreeMap 底层通过红黑树(Red-Black tree)实现,也就意味着 containsKey(), get(), put(), remove() 都有着 log(n) 的时间复杂度。

  另一个更重要的特性是,key 支持排序,这给应用层带来了无限的发挥空间。

  比如在阅读 ARouter 路由框架的时候,我就很好奇,拦截器的自定义优先级是如何实现的呢?为啥不允许多个拦截器有相同的优先级,是怎么做到的呢?开扒源码,原来是继承了 TreeMap 实现了 UniqueKeyTreeMap,数值越小就越优先添加拦截器,所以属性值设置得越低,优先级越高。

SparseArray

关键词

  双数组、引入DELETE标记删除O(1)、二分查找、避免自动装箱、满了才扩容、优化追加元素可直接追在数组末尾

前言

  SparseArray相比起HashMap来说,源码简单得多。

  我们首先要清楚 SparseArray的诞生背景和应用场景,这将影响它的特点。我们知道,谷歌官方推荐在 Android 开发中,使用SparseArray代替HashMap,那反过来想想,HashMap有什么缺点呢?

  1. 内部负载因子扩容,意味着 1 - 负载因子剩下的空间永远不会用来放元素,浪费空间!
  2. Map 的 key value 需要使用包装类型,装箱操作会创建对象,如果频繁的装箱操作会消耗许多内存。

SparseArray又是怎么解决这个问题的呢?一切答案尽在下面的博文中。

博文

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值