面试
迪恩_Emma
喜欢看书的Java开发
展开
-
既然有了字节流,为什么还要有字符流?
因为字节流转换成字符流,过程很耗时。如果你必须要使用字符流,但你只得到了字节流,就要经历这个转换,其中编码也容易出问题。所以就直接把字符流单独作为了一个部分,从而提高使用字符流的效率。...原创 2021-05-29 16:02:08 · 2820 阅读 · 0 评论 -
手撕HashMap代码
写put、get、remove方法public class MyHashMap { static class Node { int key, value; Node next; public Node(int key, int value) { this.key = key; this.value = value; } } private final int C原创 2021-05-22 15:55:52 · 118 阅读 · 0 评论 -
equals和==的区别
equals比较的是值是否相同,==比较的是引用是否相同(equals被重写过的话就是比较值是否相同,如果没有被重写,也是比较引用)原创 2021-05-11 15:58:48 · 66 阅读 · 0 评论 -
redis参数
redis的8大参数:String、hash、list、set、zset、bitmaps、hyperloglogs、streamsString应用场景:微信点赞、阅读量新建:set key valueset myid 2增加:incr myid 1 (如果是微信点赞,myid表示自己的微信id,1代表点赞的数量,而不是点赞者的id)减少:decr myid 2(减2)hash应用场景:购物车新建:hset key field value...原创 2021-05-11 15:38:29 · 328 阅读 · 0 评论 -
最左匹配原则
联合索引的底层也是一棵B+树,但是联合索引的键值数量不止一个。构建一棵B+树只能根据一个值来构建,因此依据联合索引最左的字段来构建B+树从最左边的值开始连续匹配原创 2021-05-10 11:16:04 · 174 阅读 · 0 评论 -
Mysql索引
聚簇索引(InnoDB)数据和索引存储在一起。只要找到了索引就找到了数据文件会将磁盘数据按照一列或者多列的值进行排序,通常是按照主键内一列的值进行排序一张表中只存在一个聚簇索引,也称为主键索引非聚簇索引(MyLsam)数据和索引分开存储非聚簇索引查询数据的过程:1)先查到聚簇索引的key2)用这个key去查询真正的数据(回表)非聚簇索引需要查询两次查询得时候使用聚簇索引能提高查询效率,尽量避免走非聚簇索引回表的耗时操作联合索引最左匹配原则..原创 2021-05-08 21:38:44 · 148 阅读 · 0 评论 -
AB抛硬币,A先抛,谁先抛到正面谁赢,问两者赢的概率
第一次:正第三次:反反正第五次:反反反反正.......第N次:反反。。。。正p=1/2+(1/2)^3+(1/2)^5+······+(1/2)^(2n+1)=1/2*(1+1/4+(1/4)^2+……+(1/4)^n)当公比不为1时,等比数列的求和公式为:Sn=[a1(1-q^n)]/(1-q)对于一个无穷递降数列,数列的公比小于1,当上式得n趋向于正无穷大时,分子括号中的值趋近于1,取极限即得无穷递减数列求和公式S=a1/(1-q)所以:...转载 2021-05-08 20:48:43 · 2634 阅读 · 0 评论 -
圆形湖中间一只鸭,岸边一只老虎,鸭的速度为s,老虎速度为4s,湖半径为r,鸭子到岸边即可安全逃脱,问什么情况下鸭子能顺利逃脱
一只老虎在追一只鸭子,鸭子逃到了一个正圆形池塘的圆心O位置,老虎不会游泳,鸭子也不能在水面上起飞,老虎奔跑的速度是鸭子游泳速度的4倍。假设鸭子和老虎分别遵循着最优的逃跑和追逐策略,请问:鸭子能不能安全地游到池塘边并起飞?如果能,如何才能做到?解:设圆的半径是R,由已知鸭子的速度是V,老虎的速度是4V,可以得知,当鸭子在距离圆心R/4之内(图中深色部分)围绕圆心做圆周运动时,角速度要大于老虎。我们暂且假定它就在一个半径为R/4的小圆上围绕圆心游走,只要经过一段时间追赶,鸭子一定会游到这样一个位置,它在..转载 2021-05-08 21:01:28 · 1061 阅读 · 0 评论 -
悲观锁、乐观锁的区别及使用场景
悲观锁:每次获取到数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁期间对该数据进行读写的其他线程都会进行等待乐观锁:每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁。但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新;如果没有被修改,则进行数据更新期间该数据可以被其他线程进行读写操作适用场景:悲观锁:适合写..原创 2021-05-08 20:39:12 · 1517 阅读 · 0 评论 -
幻读是什么?MySQL怎么解决幻读?
原创 2021-05-08 20:08:49 · 95 阅读 · 0 评论 -
sychronized底层原理,为什么慢?
sychronized是重量级锁:同一时刻有多个线程竞争同一把锁当多个线程竞争同一把锁时,竞争失败的线程会被阻塞。直到只有锁的线程将锁释放后再次唤醒阻塞的线程慢的原因:线程的唤醒和阻塞是一个很耗费CPU资源的操作优化:使用自旋锁来获取重量级锁,线程未获得锁后,不是一味地阻塞,而是让线程通过循环不断尝试获取锁自旋锁的缺点:若线程占用锁的时间过长,导致CPU资源拜拜浪费...原创 2021-05-08 20:01:26 · 557 阅读 · 0 评论 -
DNS解析过程
DNS解析过程: 1)客户机提出域名解析请求,并将该请求送出给本地的域名办事器。 2)当本地的域名办事器收到请求后,就先查询本地的缓存,如果有该纪录项,则本地的域名办事器就直接把查询的结果返回。 3)如果本地的缓存中没有该纪录,则本地域名办事器就直接把请求发给根域名办事器,然后根域名办事器再返回给本地域名办事器一个所查询域(根的子域) 的主域名办事器的地址。 4*)本地办事器再向上一步返回的域名办事器送出请求,接受请求的办事器查询自己的缓存,如果没有该纪录,则返回相关的下级的域原创 2021-05-06 22:38:33 · 88 阅读 · 0 评论 -
B+树对比B树的好处
B-树检索原理:每个节点保存键值对、指针、数据比平衡二叉树(AVL)减少了一次IO操作B+树检索原理:1)非叶子节点只存储键值信息(且每个磁盘块只能存储3个键值及指针信息)数据只存储在同一层的叶子节点上2)叶子节点之间,增加了链表,不再需要中序遍历B树和B+树的比较:B树结构:如果数据量较大时,会导致每个节点能存储的key的数量变少,同样会导致B树的深度较大,增大查询时的磁盘IO次数B+树结构:所有数据都按照键值大小顺序...原创 2021-05-06 22:26:30 · 912 阅读 · 0 评论 -
rehash
rehash存在于HashMap和redis中:它是在扩容的时候使用例如:HashMap在进行扩容时,会调用resize()函数,重新计算HashMap所需的新容量,然后重新定义一个新容器,将原数组数据进行Hash,放入新的容器中。这个过程就是rehash。而redis和HashMap的区别:redis的rehash操作采用渐进式,慢慢将所有键值对迁移到新的哈希表中而HashMap是一次性的操作,每次扩容需要将所有键值对都迁移到新的数组中,会很消耗时间...原创 2021-05-05 22:18:34 · 188 阅读 · 0 评论 -
创建线程池的方法?
线程池的三个常用创建方式:1)newFixedThreadPool() 一池固定多少个线程2)new SingleThreadExecutor() 一池一个线程3)newCachedThreadPool() 一池N个处理线程(N由系统决定)但是在实际开发中不能用以上的三种,要用自定义的线程池,原因是:(阿里巴巴Java开发手册中写到)自定义的线程池:...原创 2021-05-05 21:54:18 · 108 阅读 · 0 评论 -
线程池的创建过程
当调用execute()方法添加一个任务时,线程池会判断:1)如果正在运行的线程数量小于corePoolSize,就马上创建线程执行这个任务2)如果正在运行的线程数量大于等于corePoolSize,就将这个任务放入阻塞队列中3)如果这时阻塞队列满了,而且正在运行的线程数量小于maximumPoolSIze,也马上创建线程执行这个任务4)如果阻塞队列满了,正在允许的线程数量大于等于maximumPoolSize,就会执行拒绝策略5)当一个线程完成任务,就会从阻塞队列中取出下一个任务来执行原创 2021-05-05 21:48:11 · 567 阅读 · 0 评论 -
线程池的七大参数
1)corePoolSize 线程池中的常驻核心线程数2)maximumPookSize 线程池能同时执行的最大线程数3)keepAliveTime 多余空闲线程的存活时间当线程数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,多余空闲线程会被销毁直到剩下corePoolSize个线程为止4)unit 多余线程的存活时间keepAliveTime的单位5)workQueue 阻塞队列6)threadFactory 创建线程的工厂7)handle..原创 2021-05-05 21:43:00 · 224 阅读 · 0 评论 -
start()和run()的区别
首先讲讲线程实现的2中方式:1)继承Thread类2)实现Runnable接口推荐第二种方式。因为实现接口的方式可以实现多继承Thread直接调用start()方法Thread Test = new Thread();Test.start();Runnable要先new一个Runnable对象,把Runnable对象放到Thread里,再调用start()Test impelements Runnable;Test t = new Test();Thread.原创 2021-05-05 21:23:42 · 105 阅读 · 0 评论 -
线程状态
1.初始状态new一个实例时,线程就进入了初始状态2.就绪状态(可运行状态)1)调用start()方法,就进入了可运行状态2)sleep()方法结束3)等待用户输入完毕4)锁池里的线程拿到对象5)线程时间片用完了6)其他线程join()方法调用结束3.运行状态线程调度从运行池中选择一个线程。这是线程进入运行状态的唯一方式只有就绪状态和运行状态可以互相转换4.阻塞状态失去处理器资源(除了失去CPU时间片)1)线程调用sleep()...原创 2021-05-05 21:06:28 · 90 阅读 · 0 评论 -
Synchronized和lock的区别
Synchronized和lock的区别1)来源:lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;2)异常是否释放锁:synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)3)是否响应中...原创 2021-05-04 23:01:10 · 85 阅读 · 0 评论 -
JDK1.8怎么解决HashMap死循环的问题?
JDK1.8之前出现死循环的原因:HashMap在多线程环境下,同时进行put操作,并且同时进行扩容时,会出现链表环,导致死循环JDK1.8解决之前版本出现的死循环:jdk1.8后是直接把节点放到扩容后该链表的尾节点,而jdk1.8前是直接放到头节点其实JDK1.8也会出现死循环,只是原因不同:i)链表转换为数ii)对树进行操作时...原创 2021-05-04 22:38:32 · 3099 阅读 · 0 评论 -
Spring的IOC和AOP两大特性
IOC控制反转,它是一种设计思想,指创建对象的控制权的转移。以前创建对象的主动权和时机是由自己把控,而现在这种权力转移到Spring容器中。应用程序在运行时依赖IOC容器来动态注入对象需要的外部资源这样每个对象只需要关注其自身的业务逻辑关系就可以了最直观的表达是:IOC让对象的创建不用去new了,可以由Spring自动产生,使用java 的反射机制,根据配置文件在运行时动态地去创建对象以及管理对象,并调用对象地方法IOC的三种注入方式:构造器注入、setter方法注入..原创 2021-05-04 21:46:18 · 232 阅读 · 0 评论 -
ConcurrentHashMap的底层结构,jdk1.8有了什么区别?
HashMap在多线程环境下操作不安全,在java.util.concurrent包下,提供了ConcurrentHashMap类,保证了HashMap操作安全不推荐使用Hashtable:它相当于给整个哈希表加了一把大锁,只要有一个线程访问,其他线程只能阻塞等待,并发性很差Collections.synchronizedMap也不够好,它本质也是对HashMap进行全表锁,并发性也不好JDK1.7的ConcurrentHashMap 采用了分段锁策略,将一个 HashMap..原创 2021-05-04 21:23:00 · 309 阅读 · 0 评论 -
HashMap底层原理和put
HashMap的底层其实是一个数组结构,数组中的每一项又是一个链表或者红黑树存储结构是数组+链表1.计算 key 的 hash 值。计算方式是 (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);2.检查当前数组是否为空,为空需要进行初始化,初始化容量是16,负载因子默认0.75。3.计算 key 在数组中的坐标。计算方式:(容量 - 1) & hash.因为容量总是2的次方,所以-1的值的二进...原创 2021-05-03 22:39:22 · 266 阅读 · 0 评论 -
ArrayList底层原理和扩容机制
第一阶段:确保容量大小,把元素添加进数组中add方法里,主要做了三件事:1)ensureCapacityInternal的意思是确保添加元素成功的最小集合容量,也就是确保ArrayList的容量,确认是否需要扩容size+1代表集合添加元素成功后,集合中的实际元素个数,也就是集合的最小容量2)将元素添加到elementData数组中3)将集合中的实际元素个数+1(size++)第二阶段:判断是否需要扩容ensureCapacityInternal()方法调用cal...原创 2021-05-03 21:40:06 · 1207 阅读 · 0 评论