ArrayList和LinkedList的区别
- ArrayList底层数据结构是数组实现的,LinkedList底层数据结构是基于链表实现的
- 因为数据结构不同,所以使用的场景不同,ArrayList适用于随机查询,LinkedList适用于添加和删除
- ArrayList和LinkedList都实现了list接口,但是LinkedList还实现了Deque接口,所以LinkedList还可以当队列来使用
说一下HashMap的put方法
- Put方法先根据key通过哈希算法与与运算得出数组下标
- 如果数组下标为空就把key-value封装为对象(1.7是Entry,1.8是Node)放入改下标位置
- 如果下表位置不为空,则分情况讨论:
- 如果是jdk1.7,则需要判断是否要扩容,如果要扩容就扩容,不需要扩容就生产Entry对象,并使用头插法添加到当前位置的链表中。
- 如果是jdk1.8,则先判断当前位置上的node类型,看是红黑树的node还是链表的node
- 如果node类型是链表,则把key-value封装成node对象使用尾插法插入到链表的最后位置,因为是用尾插法所以会遍历链表,如果有key相同,则更新value。遍历完链表后把新的链表node插入到链表中,插入后会判断当前链表节点的个数,如果超过8则将链表转化为红黑树。
- 如果node类型是红黑树,就会把node封装成一个红黑树节点添加到红黑树中,在添加过程中会判断key,如果key相同就会更新value。
- 将key-value封装成node插入到链表或红黑树中后,再判断是否需要扩容,如果不需要就结束put方法。
jdk1.7和jdk1.8 HashMap 发生了什么变化(底层)
- jdk1.7中底层是数组+链表,jdk1.8中底层数据结构是数组+链表+红黑树
- jdk1.7中使用的是头插法,jdk1.8中使用的是尾插法,因为1.8中要遍历链表进行判断链表节点的元素个数,所以就使用尾插法
- 1.7中哈希算法复杂度高,1.8中进行了简化,因为负载的哈希算法目的是为了提高散列性,而1.8新增了红黑树,所以可以适当的简化哈希算法,节省cpu资源
jdk1.7到jdk1.8java 虚拟机发生了什么改变
- 1.7中存在永久代,1.8中没有永久代,替换为元空间,元空间不占用虚拟机的内存,而是本地内存空间。因为不管是元空间还是永久代,它们都是方法区的具体实现,之所以改官方的说法是为了和JRockit统一,不过还有一些额外的原因;比如方法区所存的类通常是比较难以确定的,所以对于方法区的大小是比较难以确定的,太小了容易内存泄露,太多了容易造成jvm内存资源浪费,而转移到本地内存后就不会影响虚拟机的内存
Redis的数据结构及使用场景
- 字符串:可以用过来做简单的缓存,可以缓存简单的字符串,也可以缓存json格式的字符串,Redis分布式锁就是利用了这种数据结构,可以实现计数器、session共享、分布式ID
- 哈希表:可以用来存储一些key-value对,更适合存储对象
- 列表:Redis的列表通过命令的组合可以当做栈,也可以当作队列,可以用来缓存公众号、微博信息
- 集合:和列表类似,可以存储多个元素,但是不能重复,集合可以进行交集、并集、差集,从而实现我于某人的共同关注、朋友圈点赞
- 有序集合:集合是无序的,有序集合可以设置排列顺序,可以用来实现排行榜功能