将list转化成迭代器,然后将元素为奇数的删除
synchronized方法锁、对象锁和类锁讲一讲?- synchronized锁方法的意思是,多线程调用同一个对象的同步方法时会阻塞,调用不同对象的同步方法不会阻塞。
- synchronized锁代码块的意思是,多线程调用该对象的同步方法时会阻塞,一般是synchronized(this)修饰,this代表当前对象。多线程调用同一个对象的同步代码块时会阻塞,调用不同对象的同步代码块不会阻塞。
- synchronized锁类的意思一般是修饰静态方法,代表是对当前java文件的.class类加锁,与synchronized(xxx.class)效果相同。
满足三范式要求,首先设计一个学生表,包括u_id, u_name,再设计一个课程表,包括c_id, c_name,再设计一个选课关系表,属性有u_id和c_id。
DFS和BFS无重复搜索 EXPLAIN sql语句讲一讲?当一些sql语句执行时间过长时,使用explain sql来查看此条sql执行的具体情况。例如查看sql有没有使用索引,有没有做全表扫描。
mysql> explain select * from servers; +----+-------------+---------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | servers | ALL | NULL | NULL | NULL | NULL | 1 | NULL | +----+-------------+---------+------+---------------+------+---------+------+------+-------+ row in set (0.03 sec)
explain列出的信息有10列,分别是:
id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
AOP的主要注解@Aspect注解:用在类上,表名这个类是一个切面类
@Pointut注解:表名刚方法的连接点
@After,@Before:表示方法在切面前面还是后面生效
@Around:表示环绕
java不支持多继承,但可以通过以下方法实现多继承
- 类的多层继承,即B类继承A类,C类又继承B类,即C类就可以重写A类的方法。
- 内部类实现多继承,具体例子如下:
class dota { private String str = "let's play some dota"; public void play() { System.out.println(str); System.out.println("好呀好呀"); } } class lol { private String str2 = "let's play some lol"; public void play() { System.out.println(str2); System.out.println("不约"); } } class player { class dotar extends dota { @Override public void play() { super.play(); } } class loler extends lol { @Override public void play() { super.play(); } } public void play() { dotar d = new dotar(); d.play(); loler l = new loler(); l.play(); } } public class MultiExtendTest1 { public static void main(String[] args) { player p = new player(); p.play(); } }在这个例子中,plaery类中的两个内部类dotar和loler分别继承了dota 和lol ,因此在player类中就实现了多继承。 - 使用接口实现多继承。
牛客每天有很多人登录,请你统计一下牛客新登录用户的次日成功的留存率,
有一个登录(login)记录表,简况如下:
- 计算留存率的公式:第一天和第二天都登录的用户/总用户数。
- 查询总用户数:
select count(distinct(user_id)) from login;
- 查询第一天登录的玩家:
select user_id, min(date) from login group by user_id;
- 查询第二天登录的玩家以及时间,因为已经计算出第一天的玩家和时间,因此只要在第一天的基础上+1 day即可。sql中当前日期加一的用法为date(当前日期,'+1 day')。
select user_id, date(min(date),'+1 day') from login group by user_id;
- 最后计算留存率:因为计算概率,因此除法时要用round()函数,round(x,n)表示对x四舍五入,且保留n位小数。
select round(count(distinct(user_id))*1.0/(select count(distinct(user_id)) from login),3) from login where (user_id, date) in (select user_id, date(min(date),'+1 day') from login group by user_id);
本题要点 :
- mysql中要进行时间加一操作的方法。在本题中,因为其date本身就是yy-mm-dd的格式化存储,因此只要查询到日期,再在后面’+1 day’,再将其结果用date()函数规范化,即可实现加一天的操作。
- mysql中获取当前时间可以使用select now(),此操作可以获取当前日期以及时间,使用select curdate(),此操作是获取当前日期。
牛客每天有很多人登录,请你统计一下牛客每个用户最近登录是哪一天,用的是什么设备.
有一个登录(login)记录表,简况如下:
第1行表示user_id为2的用户在2020-10-12使用了客户端id为1的设备登录了牛客网
第4行表示user_id为3的用户在2020-10-13使用了客户端id为2的设备登录了牛客网
还有一个用户(user)表,简况如下:
还有一个客户端(client)表,简况如下:
请你写出一个sql语句查询每个用户最近一天登录的日子,用户的名字,以及用户用的设备的名字,并且查询结果按照user的name升序排序,上面的例子查询结果如下:
本题要点:
-
即使是多表联查,也可以尽量避免join查询,使用where代替。
-
group by, order by的使用顺序:
from->join->on->where->group by->avg,sum->(having, select)->distinct->order by->limithttps://blog.csdn.net/u014044812/article/details/51004754
https://blog.csdn.net/menghuanzhiming/article/details/79886083 -
order by不能对group by进行组内排序,因为group by分组后只能返回一条数据,因此如果要取组内最大最小,应使用max()或者min()函数。
解法一:使用where代替join
select u.name u_n, c.name c_n, max(l.date) 'date' from login l , client c , user u where l.user_id = u.id and c.id = l.client_id group by user_id order by u.name asc
解法二:
select u.name u_n, c.name c_n, max(l.date) 'date' from login l join client c join user u on l.user_id=u.id and l.client_id=c.id group by user_id order by u.name ascTCP与UDP讲一讲
切入点:
- TCP与UDP区别:TCP是面向连接的,而UDP不是,TCP是可靠的,UDP不是,TCP是字节流传输,UDP是数据报文段,TCP传输效率低,所需资源多,UDP传输效率高,所需资源少。
- TCP应用场景:邮件
- UDP应用场景:视频、语言、即时通信(QQ)
- 应用数据被分割成 TCP 认为最适合发送的数据块。
- TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
- 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
- TCP 的接收端会丢弃重复的数据。
- 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
- 拥塞控制: 当网络拥塞时,减少数据的发送。
- ARQ 协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
- 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。
拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。
为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。
TCP 的拥塞控制采用了四种算法,即慢开始、拥塞避免、快重传和快恢复。
- 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍。
- 拥塞避免: 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送放的 cwnd 加 1.
- 快重传与快恢复: 在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
- Spring Core:核心模块, Spring 其他所有的功能基本都需要依赖于该类库,主要提供 IoC 依赖注入功能的支持。
- Spring Aspects:该模块为与 AspectJ 的集成提供支持。
- Spring AOP:提供了面向切面的编程实现。
- Spring Data Access/Integration:由 5 个模块组成,spring-jdbc、spring-tx、spring-orm、spring-oxm、spring-jms
- Spring Web:主要有Spring-web、spring-webmvc、spring-websocket
- Spring Test:单元测试
IOC是一种设计思想,IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。将对象之间的相互依赖关系交给IoC容器来管理,并由IoC容器完成对象的注入。IoC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
AOP是面向切面编程,能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理
讲一讲SpringMVC的工作原理流程:
- 客户端发送请求到DispatcherServlet。
- DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
- 解析到对应的Handler(也就是我们平时常说的Controller控制器)后,开始由HandlerAdapter适配器处理。
- HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。
- 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View 是个逻辑上的View。
- ViewResolver会根据逻辑View查找实际的View。
- DispaterServlet把返回的Model传给View(视图渲染)。
- 把View返回给请求者(浏览器)。
-
首先所有的springboot程序都是从SpringApplication.run()方法启动,在这个类上有一个@SpringBootApplication注解,表明这是一个springboot程序。
-
在@SpringBootApplication注解中,有三个重要的注解,分别是@SpringBootConfiguration,@EnableAutoConfiguration和@ComponentScan
-
其中@SpringBootConfiguration代表该类是一个的配置类,通过@Configuration和@Bean注解相结合,将Bean注册到Spring ioc容器中。
-
@ComponentScan注解的作用是自动扫描该类所在包下所有的配置类。
-
Spring Boot自动装配的核心是@EnableAutoConfiguration注解,而@EnableAutoConfiguration又导入了AutoConfigurationimportSelector这个类。
-
在AutoConfigurationimportSelector中,我们可以看见它实现了importSelector接口,并实现了该接口的selectimports方法
而selectimports方法主要用于获取所有符合条件的全类名,并在这些类加载到IoC容器中。在selectimports方法中还有一个getAutoConfigurationEntry()方法,这个方法主要负责加载自动配置类的。 -
而在getAutoConfigurationEntry()方法中,又有四个步骤:
第一步:判断自动装配开关是否打开,spring.boot.enableautoconfiguration=true,可以在application.properties和application.yml中修改。
第二步:获取@EnableAutoConfiguration注解中的exclude和excludeName
第三步:获取需要自动装配的所有配置类,读取meta-INF/spring.factories
spring-boot/spring-boot-project/spring-boot-autoconfigure/src/main/resources/meta-INF/spring.factories
第四步:筛选,使用@ConditionalOnXXX注解来判断要舍弃哪些注解
可以看到经过这一步后,加载的类的数量从之前的131降到了24.



