java集合

145 阅读2分钟

参考文章

java集合分类

java集合分为Collection和Map两个接口,Collection下有List、Queue、Set三个子接口,具体看下图。

List

Vector、ArrayList和LinkedList

  • Vector和ArrayList底层都是用数组实现,但Vector方法多数加了synchronized。另外Vecotr扩容为2倍,ArrayList为1.5倍。ArrayList初始容量为10。
  • LinkedList底层实现是链表,实现了Queue、Deque等接口, 除了头尾插入新节点,其他位置新增节点均需要O(n)时间复杂度。

HashMap

jdk1.7实现

  • 初始容量16,加载因子0.75,加载阈值12(16*0.75),一般扩容为当前容量的2倍。推荐集合初始化时,指定集合初始值大小(初始值如何确定未知)。

  • table是Entry 数组。我们都知道 HashMap 内部存储 key/value 是通过 Entry 这个介质来实现的。而 table 就是 Entry 数组。要找个jdk1.7看看table的结构,Entry是否是链表,hash碰撞下如何做到头插法?

  • JDK1.7 中 HashMap 由 数组+链表 组成(“链表散列” 即数组和链表的结合体),数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(HashMap 采用 “拉链法也就是链地址法” 解决冲突)

  • 如果定位到的数组位置不含链表(当前 entry 的 next 指向 null ),那么对于查找,添加等操作很快,仅需一次寻址即可

  • 如果定位到的数组包含链表,对于添加操作,其时间复杂度依然为 O(1),因为最新的 Entry 会插入链表头部,即需要简单改变引用链即可,而对于查找操作来讲,此时就需要遍历链表,然后通过 key 对象的 equals 方法逐一比对查找。

  • jdk1.7中hashmap的数据存放示意图

jdk1.8实现

小博哥_HashMap

  • 初始化等与1.7一致
  • 链表长度大于阈值(默认为8)时,将链表转化为红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
  • hash过程是:(对这块不理解释可以参看最上的两个链接)
    • 获取key的hashcode值h
    • 将h右移16位并与h异或(h^(h>>>16))得到新的hash值h1
    • hashmap的长度length,与h1进行与运算,(length-1)&h1
    • (length-1)&h1等同于 h1对length求余
    • 目的是为了数据分配均匀,也就是散列的效果更好,减少hash的碰撞