Java集合总结

  1. 集合源码
    1. ArrayList
      • 底层是数组实现,能够自动扩容,是个动态数组
      • 初始化时是个空数组,初始容量大小为10,但不是初始化了一个大小为10的数组
      • 第一次add的时候,初始化为容量10
      • 自动扩容是当前的1.5倍,使用了右移位运算 >> ,即除于2
      • 增删效率慢,通过下标获取速度非常快O(1)
        1. 增加时会涉及到扩容,删除时会设计到数组元素移动,所以速率慢
        2. 删除时,如果不是删除尾部的元素,数组会往前移动,效率低
        3. 增加时,会在尾部增加,尾部增加时效率还是很快的,如果在数组中间增加,则需要将元素右移,速率非常低,当数组容量不够时,需要扩容,扩容需要消耗大量时间
      • 非线程安全
    2. Vector
      • 底层是数组实现
      • 初始化时可以是数组,也可以是开发指定的数组大小
      • 扩容时,默认是当前的两倍,也可以由开发指定扩容的大小
      • 线程安全,每个方法加了Syncronized关键字
      • 2,3,4是跟ArrayList的区别
    3. LinkedList
      • 底层是双向链表实现
      • 初始化时什么也没做,懒惰性增加元素
      • 增加时,采用尾插法,将尾部的指针指向当前元素
      • 不存在扩容问题,只要内存够大,就能无限增加元素
      • 增删效率快,不通过下标获取时的时间复杂度是O(n)
      • 通过下标获取节点时,采用的折半查找法,时间复杂度是O(logN)
      • 1.6之前采用的是双向循环链表,1.7取消循环,单单双向链表
    4. HashSet
      • 底层还是用的散列表
      • 初始化容量是16
      • 初始化的时候直接new了一个HashMap
      • 增加的时候,直接把值放在HashMap的键位置,因此是散列无序的,且是不能重复的原因
      • 增加的值放在HashMap的key位置,value存的是一个静态Object对象
      • 扩容时,容量是原来的两倍
    5. HashMap
      • 底层采用的是散列表,解决哈希冲突的方法是“拉链法”
      • 初始化容量是16,哈希因子是0.75
      • 哈希因子 = 容纳元素个数/数组的长度,因此初始化可容纳的元素个数是12
      • 变成红黑树的条件:数组长度大于64,且链表的长达大于8,需这要两个条件
      • 当红黑树的节点数量小于6的时候,又会退化为链表
      • 通过哈希值计算出在数组上的位置,当产生哈希冲突时,增加链表存储元素
        1. 1.7是通过头插法建立链表
        2. 1.8是通过尾插法建立链表
      • 当key相等的时候,如果值不一样,就会替换掉值
      • 数据结构
        1. 哈希函数
          1. 取模法  100%30=3
          2. 取余法   100/30 = 10
          3. 平方取中法  11的平方=121 = 2
          4. 数学计数法
          5. 折叠法
        2. 解决哈希冲突的方法
          1. 线性探测法
          2. 二次线性探测法
          3. 拉链法(hashmap采用这种解决冲突,即数组+链表)
        3. 哈希因子 = 数据个数/数组的容量
      • Map底层由哈希表实现。
        1. JDK1.8之前:数组+链表。
        2. JDK1.8以后:数组+链表,数量多时自动升级为数组+红黑树
          1. 什么时候链表升级为红黑树?
            1. 链表长达大于8,且数组大于64时升级为红黑树
            2. 当链表小于6时,又降为链表
          2. 为什么加入红黑树?
            1. 红黑树查找速度快,时间复杂度为logn
      • 相关解答
        1. 哈希因子
          1. 默认是0.75
        2. 数组长度
          1. 默认是1<<4 = 16
        3. 最大容量 1<<30
        4. 何时扩容?
          1. 当数组的数据大于16 * 0.75 = 12时,需要扩容
          2. 扩容机制大小为原来的两倍  大小<<1
        5. 为啥哈希因子要用0.75
          1. 0.5太浪费空间
          2. 1.0密度太大
          3. 折中取0.75
        6. 解决冲突(拉链法)
          1. 当计算出的哈希值一样时,如果键key一样,那么值value会被覆盖
          2. 如果键key不一样,则新增节点
            1. Jdk1.7头插法
            2. Jdk1.8尾插法
        7. 节点问题
          1. Jdk1.7用Entry[]
          2. Jdk1.8用Node[]
          3. 其实就改了个名字,没有本质的区别
    6. LinkedHashmap
      • 有序的hashmap,即取出的元素按照插入的顺序取出
      • 原理是put的时候,使用双向链表把put的元素串联起来
    7. LinkedHashSet
      • 有序的hashset,
      • 原理是底层用LinkdedHashMap的key作为值存入
    8. TreeSet
      • TreeSet的元素有序,是根据一定的规则进行排序,因为平衡二叉树
      • TreeSet可以根据指定的比较器进行排序
      • TreeSet不允许元素数据重复
  2. 集合比较
    1. ArrayList和LinkedList的区别
      • 两者都是非线程安全
      • ArrayList底层是数组,LinkedList底层是双向链表
      • 速率问题
        1. ArrayList通过下标查找速率非常高,直接就是O(1),增加和删除因为涉及扩容或者移动,所以速率是比LinkedList慢的,当然ArrayList在数组尾部增加元素还是蛮快的
        2. LinkedList查找的时候比ArrayList慢,因为要从头到尾扫一遍,增加和删除的时候速度是非常快的,不用移动元素,只需要控制好指针的指向即可,且LinkedList增加元素是采用的尾插法
    2. ArrayList和Vector的区别
      • Vector初始化时,可以指定数组初始化大小,ArrayList不可以
      • Vector是线程安全的,用Syncronized修饰方法,而ArrayList是线程不安全的
      • Vecotr默认扩容是原来的2倍,ArrayList默认扩容是原来的1.5倍
      • Vecotr可以指定扩容的大小,ArrayList不可以指定扩容的大小,比如Vector可以指定扩容大小为20
    3. HashSet和HashMap的区别
      • HashSet存的元素不能为null,而HashMap可以存一个key为null,可以存多个值为null
      • HashSet底层也是使用的HashMap,用HashMap的key来存值
      • HashSet是实现的set的接口,HashMap实现的是Map接口
      • HashSet增加元素是add方法,HashMap增加元素是put方法
      • HashSet存的是对象,HashMap存储的是键值对
    4. HashTable和HashMap的区别
      • HashTable是线程安全的,方法都用Syncronized修饰,而HashMap是线程不安全的
      • HashTable不能存key和value不能存null,只要有一个存null,就会报空指针异常,而HashMap可以存一个key为null,可以存多个值为null
      • HashTable的效率比HashMap慢
    5. ConcurrenHashMap和HashMap的区别
      • ConcurrenHashMap是线程安全的,HashMap是线程不安全的
  3. 关于HashCode
    1. HashCOde方法是属于Objcet父类提供的方法
    2. 在Java运行期间,在同一个对象上多次调用hashCode方法时,一致地返回相同的整数
    3. HashCode的存在主要是用于查找的快捷性,如HashTable,HashMap等,HashCOde是用来在散列存储结构中确定对象的存储地址
    4. 如果equals方法比较相等,则HashCode值也一定相等,但是HashCode相等,不代表equals比较也相等
      • 举例:‘a’和97的哈希值相等,因为ACSCCl码,所以哈希值相等,但是他们的equals肯定是不相等的
    5. 如果重写了equeals方法,必须要重写HashCOde方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值