java datastructure

ArrayList: 动态数组, 默认的扩容 oldCapacity + (oldCapacity >> 1), 通过System.arraycopy copy数组.
AbstractList modCount fail-fast, 对于改变list capacity 的每次操作都会++modCount, 在AbstractList 迭代器迭代过程中如果modCount 发生改变, 迭代器中的expectedModCount没有
重新复制为modCount 就会报错, 这是为了防止并发对list修改, 多线程中建议使用CopyOnWriteArrayList。


HashMap: 数组+链表, hashcode 为key, 相同hashcode 位于同一链表中. HashMap 内部数组transient Node<K,V>[] table, Node implements Map.Entry 为单向链表.
 put 操作: new HashMap() 默认是不初始化table, 懒加载. put 先resize() 初始化table, table[hash]值是否存在, 不存在创建Node(hashCode, k, v, null)赋值table[hash], 如果table[hash]存在即发生hash冲突, 此时以table[hash]第一个节点作为根节点, 向下查找, 如果key相同(== 或者equals判断) 直接替换value, 不存在直接插入到最后的节点,在for循环查找链表中的节点时, 如果循环的次数(binCount) 大于TREEIFY_THRESHOLD=8 也就是说链表的长度大于8, 需要将此链表转变为red-black tree(插入的时间复杂度O(log(n)) 链表的为O(n), 遍历的时间复杂度O(N) 链表的O(N)),提高了插入操作的效率. 节点变为TreeNode(TreeNode 有parent, left, right, prev, boolean red). 如果新增元素也会使++modCount.
   remove 操作: 比较简单, 通过key找到对应的table位置, 在链表或者二叉树中删除该位置的节点即可(链表的话是第一个就table[hash] = root.next, 不是第一个就pre.next = currentNode.next, 二叉树有点复杂尤其是红黑树涉及到左旋右旋), ++modCount
   hash()方法: 通过key的hashCode的低16位和高16位做异或运算作为新的低16, 如果key null返回0, 这么做的原因是扰动hash 使hash 结果和table length n做与运算尽可能分布均匀, 就是主要看hash的低位和n的与运算结果
   resize()方法: Node<K,V>[] table为null, 需要初始化, 初始化的capacity 为DEFAULT_INITIAL_CAPACITY=1<<<4, threshold 变为DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY = 12. 如果table的数组的数据大于threshold=12,就会进行resize(), capacity 和 threshold 都会<<1, 然后copy原来的数据到新的table中, jdk8 做了优化, 如果table[i]的node.next=null, 就直接node.hash & newThr-1, 如果node.next !=null, 就需要将链表的所有节点重新分配, 因为newThr的改变会导致原来在同一个链表上的node变为2个链表, 只需要查看newThr的非0最高位1(可能描述不正确)和node.hash的与结果是0还是1, 我们就能确定node新的位置是原来的位置还是原来位置+非0最高位, 免去了rehash. 以默认容量16为例, 假如新加元素导致table 12个位置被填充数据, 需要resize(), 首先扩容16<<1=32, 然后拷贝数据到新的table中, 如果oldTable[i].next=null, 直接oldTable[i].hash & 32 -1 作为在newTable中的位置, 否则对这个链表中的每个节点重新分配, 只需要对比oldTable[i].hash & 32, 32的2进制为100000, 如果这个值为0, 说明oldTable[i].hash 的第6位是0 和32-1做与运算的结果和16-1的结果一样, 所以位置不变, 如果是1则和32-1的与运算结果比16-1的多了100000即16也就是原来的容量大小, 新位置就是i+oldCap.(没有讨论红黑树的情况, 有点复杂)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值