遍历ArrayList时移除一个元素foreach删除会导致快速失败问题,可以使用迭代器的remove()方法

  1. Iterator itr=list.iterator();
  2. while(itr.hashNext()){
  3. if(itr.next().equals("jay")){
  4. itr.remove();
  5. }
  6. }

list、set、map的区别list是有序,下标,可重复,可空,数组
set是无序,map的键,不可重复,只能一个可空,基于map实现(基于hash存储和红黑树)
map无序,键值对,但底层也是数组,不可重复,可空,基于hash存储和红黑树 ArrayList和vector区别

  1. Arraylist默认扩容50%,线程不安全
  2. Vector线程安全,默认扩容一倍 ArrayList和LinkedList区别
  3. ArrayList基于动态数组,LinkedList基于链表
  4. ArrayList下标查询,LinkedList指针遍历,所以查询和修改速度优于LinkedList HashMap

    put方法流程?
  5. 判断map是否为null,是就执行resize()扩容

  6. 根据hashcode&(length-1)计算key的索引,如果索引处为null,直接插入节点,否则遍历当前链表或红黑树。如果有数据的key和hash和插入的相同,就替换,没有就尾插。
  7. 添加元素后,看是否需要扩容,如果链表长度>8,再看数组容量,如果>64就转红黑树,如果<64就扩容

    HashMap扩容机制

    当元素个数超过数组大小*负载因子(默认值0.75)时扩容,用尾插法转移到新数组,每次扩容一倍,所以hashmap最小大小是16。
    1.7之前是头插法,在多线程的情况下,原先按顺序排列的链表有可能出现首尾相连的问题,所以在1.8之后采用尾插法。

    为什么加载因子默认是0.75

    对时间和空间成本上的折中,对空间和时间效率的最佳平衡,对于泊松分布,负载因子取0.75时,λ=0.5,碰撞最小,链表数量达到8个时的概率变得非常小,长度大于8几乎不可能,从而也决定了红黑树和链表切换的节点是8

    hash冲突如何解决
  8. hashmap引入链式寻址法,把存在冲突的key组成一个单向链表,采用尾插法把key保存到链表的尾部

  9. 另外解决hash冲突的方法有很多

    1. 再hash法,如果某个函数产生了冲突,再用另外一个hash函数进行计算
    2. 开放定址法,以key计算出的hashcode再次hash。
    3. 建立公共溢出区,把存在冲突的key统一放在一个公共溢出区里。
      在解决hash冲突时,为什么选择先用链表,再转红黑树
      因为红黑树需要左旋、右旋、变色这些操作来保持平衡,而单链表不需要。因为红黑树新增效率慢,当元素个数小于8的时候,采用链表性能更高,元素大于8个、数组容量小于64时,链表查询速度慢,会采用红黑树加快查询速度。
      什么时候红黑树退回链表
      数组扩容时会执行resize()方法,将会调用split()重组红黑树,如果节点数少于6个就退回到链表。
      HashMap的长度为什么是2的幂次方
      数据存入map时,是用数据的key的hash值%hashmap的长度得到的值作为数据在数组的下标,按位与的计算速度更快,于是优化成hashcode&(length-1)和之前%的结果一样,再后来利用(2^n)-1 的二进制数每一位都是1的特性,&((2^n)-1)每次都会得到不同的值,可以有效减少hash碰撞。所以就设定长度为2的n次方了。
      一般用什么作为key
      一般使用Integer、String这种不可变的类当HashMap的key,String类比较常用。
  10. 因为string类型的值在创建时的hashcode就被缓存了,不需要重新计算

  11. 获取对象时要用到equals()和hashCode()方法,而string、integer这些都已经重写了这两个方法,不需要额外重写。

    为什么线程不安全
  12. jdk1.7使用头插法,在多线程环境下,扩容可能导致环形链表的出现,形成死循环。

  13. jdk1.8后,在多线程环境下,会发送数据覆盖的情况

    HashMap和HashTable区别
  14. HashTable是jdk1遗留下来的类,在jdk1.5以后提供了ConcurrentHashMap替代它;HashMap是后来增加的

  15. HashTable线程安全,HashMap线程不安全
  16. HashTable的key不允许为null,HashMap可以有一个null,放在下标为0的头节点的链表中。
  17. HashTable很多方法是同步方法,在单线程环境下比HashMap慢
  18. HashTable直接使用对象的HashCode,HashMap重新计算hash值
    ConcurentHashMap