Java基础常识及面试(四)

一、基础

1、集合

1)类关系图

2)集合

集合ArrayListLin  
     
     
     
     

 

 

 

 

 

 

list如何扩容

2、IO

3、多线程

4、异常

5、网络编程

二、框架

1、SpringMVC

1)用户发送请求---》DispatcherServlet中央控制器

2)DispatcherServlet调用处理器映射器找到处理器---》HandlerMapping处理器映射器

3)HandlerMapping返回HandlerExcutionChain给Dispatcher

4)DispatcherServlet---》调用HandlerAdapter---》Controller-

5)Controller---》返回ModelAndView--》HandlerAdapter---》返回ModelAndView--》DispatcherServlet

6)DispatcherServlet---》视图解析viewResolver--》返回view--》DispatcherServlet

7)DispatcherServlet---》渲染视图view

8)DispatcherServlet----》相应用户

2、Spring

Spring生态、Spring技术栈

 

IOC

 

AOP

1)如何给单个方法加入切面

 

Bean

 

Spring事务

 

3、Mybatis

1)#{}和${}的区别

2)Mybatis的传值方式

方法1:顺序传参法

1
2
3
4
5
6
public User selectUser(String name, int deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{0} and dept_id = #{1}
</select>

#{}里面的数字代表你传入参数的顺序。

这种方法不建议使用,sql层表达不直观,且一旦顺序调整容易出错。

方法2:@Param注解传参法

1
2
3
4
5
6
public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

#{}里面的名称对应的是注解@Param括号里面修饰的名称。

这种方法在参数不多的情况还是比较直观的,推荐使用。

方法3:Map传参法

1
2
3
4
5
6
public User selectUser(Map<String, Object> params);

<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

#{}里面的名称对应的是Map里面的key名称。

这种方法适合传递多个参数,且参数易变能灵活传递的情况。

方法4:Java Bean传参法

1
2
3
4
5
6
public User selectUser(Map<String, Object> params);

<select id="selectUser" parameterType="com.test.User" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

#{}里面的名称对应的是User类里面的成员属性。

这种方法很直观,但需要建一个实体类,扩展不容易,需要加属性,看情况使用。

 

4、SpringBoot

优点

 

5、SpringCloud

6、Dubbo

7、Zookeeper

三、数据库

1、存储过程

sql语句需要先编译然后执行,而存储过程(Sroed Procedure)十一组为了完成特定功能的sql语句集,经编译后存储在数据库中,用户通过制定存储过程的名字并给定参数(如果存储过程中带有参数)来调用它

存储过程是可编程的函数,在数据库总创建并保存,可以由sql语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定的动能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式

优点

1)增强sql语音的功能和灵活性

2)标准组件式编程

3)较快的执行速度

2、sql语句

from表索引---》where过滤条件---》Group By分组---》Having对分组数据过滤条件---》select那些列,及计算---》order by 排序

left join左连接--》返回包括坐标的所有记录和右边中连接字段相等的记录

right join右连接---》返回包括右表中所有记录和左表中连接字段相等的记录

inner join等值连接---》只返回俩个表中连接字段相等的行

3、数据库优化

3.1、数据库压力变大,读写分离

主从数据库之间的数据需要同步(可以使用mysql自带的master-slave方式实现主从复制)

应用中需要根据业务进行对应的数据源选择(可以采用第三方数据库中间件,例如mycat)

3.2、使用搜索引擎缓解读库的压力

创建普通索引:

CREATE INDEX username ON mytable(username);

创建唯一索引:不重复。列值唯一,但是唯一索引可以有空值。

CREATE UNIQUE INDEX age ON mytable(age); 

创建主键索引:主键索引不可以有空值。

ALTER TABLE mytable ADD PRIMARY KEY (id);

删除索引

DROP INDEX 索引的名字 ON 索引的表;

 组合索引

ALTER TABLE mytable ADD INDEX name_city_age (username,city,age);

全文索引

CREATE FULLTEXT INDEX index_content ON article(content)

  修改索引

ALTER table mytable ADD UNIQUE [indexName] (username(length))

 显示索引信息

SHOW INDEX FROM table_name

B+树的查询时间---》树的高度,log(n)
hash存储索引---》o(1)
树---》前中后便利、二叉树、二叉搜索树、平衡二叉树、红黑树、B树、B+树、字典树

1)二叉排序数据

左边根节点小,右边根节点大,并且左右子树都是二叉排序树


有序序列,二叉排序树退化成链表

2)平衡树
    
插入的时候调整这棵树,让它的节点尽可能平均分布
树的查找性能取决于树的高度,让树尽量平衡,就是为了降低树的高度

3)B树(文件系统索引)
是一种多路搜索树,他的每个子节点可以拥有多于俩个孩子节点。M路的B树最多可以拥有M个孩子节点
进一步降低树的高度
不限制路数,B树就退化成一个有序数组了
文件系统和数据库的索引都是存储在硬盘上,并且如果数据量大的化,不一定能一次性加载到内存中(程序运行时内存情况)
可以每次加载B树的一个节点,然后一步步往下找
假设内存一次最多加载2个数

3)B+树(数据库索引)

是在B树的基础上进行改造,它的数据都在叶子结点,同时叶子结点之间还加了指针形成链表
    
如果是多条的话,B树需要做局部的中序遍历,可能要跨层访问。而B+树由于所有数据都在叶子结点,不用跨层,
同时由于有链表结构,只需要找到首尾,通过链表就能把所有数据取出来了。

如果一张表用hash更快,但数据库中经常会选择多条,这时候B+树索引有序,并且又有链表相连,它的查询效率比hash就快很多了。

而且数据库中的索引一般是在磁盘上,数据量大的情况可能无法一次装入内存,B+树的设计可以允许数据分批加载,同时树的高度较低,提高查找效率。

3.3、引入缓存机制缓解数据库的压力

Memcache

Redis

3.4、某些场景下,可以对用户的某些IP的访问频率做限制

那这方内存中不合适,放数据库又太麻烦,这个时候可以用Nosql的方式来代替传统的关系型数据库

MongDB

3.5、数据库的水平/垂直拆分

垂直拆分:把数据库不同业务的数据拆分到不同的数据库中

水平拆分:把同一个表中的数据拆分到俩个甚至更多的数据库中,水平拆分的原因是某些业务数据量已经达到单个数据库的瓶颈,这个时候可以采取拆分到多个数据库中

四、数据结构

五、设计模式

六、Linux

七、其他知识

1、Docker

2、jenkins

3、Elasticsearch

八、前端

1、Node.js

2、MVVN

vue.js

九、JVM

十、编程题

1、输入一行字符,分别统计其英文字母、空格、数字和其他字符个数

定义变量   if else循环判断  输入Scanner(System.in)对象;  a.nextLine获取String ,
将String转换为toCharArray();  isDigit是否数字  isSpaceChar(arr[i])是否空格 isLetter是否字母

  public static void main(String[] args) {
        int num = 0;
        int spcae = 0;
        int england = 0;
        int qita= 0;
        Scanner s = new Scanner(System.in);
        
        String a = s.nextLine();
        char[] arr = a.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            if(Character.isDigit(arr[i])) {
                num++;
            }else if(Character.isSpaceChar(arr[i])) {
                spcae++;
            }else if(Character.isLetter(arr[i])) {
                england++;
            }else {
                qita++;
            }
        }
        System.out.println(num);
        System.out.println(spcae);
        System.out.println(england);
        System.out.println(qita);
    }

2、将一个数组逆顺序输出
     要求实现函数(不能调用api)
     void Rev(int InputArray[].unsigned int n)
    【输入】InputArray 给定的数组        n:数组的长度
    【输出】InputArray:你顺序的数组
    【返回】无

    1、将数组转换为ArrayList    Arrays.asList(s);
    2、调用集合工具类Conllections.reverse(list);
    3、list.toArray(s);

    
    public static void main(String[] args) {
        int InputArray [] = new int[] {1,2,3,4,6,7};
        int n = InputArray.length;
        Rev(InputArray, n);
    }
    
    public static void Rev(int InputArray[],int n) {
        for (int i = n - 1; i >= 0; --i) { // 逆序输出
            System.out.print(InputArray[i] + " ");
        }
    }

3、写一段代码,判断一个包括’{‘,’[‘,’(‘,’)’,’]’,’}’的表达式是否合法(注意看样例的合法规则。) 
给定一个表达式A,请返回一个bool值,代表它是否合法。

解析:利用栈来做,当遇到 ‘{‘, ‘[‘, ‘(’ 等就把当前的括号字符入栈,当遇到 ‘)’ , ‘]’ , ‘}’ 
就出栈一个括号字符。最后判断栈是否为空,栈空则表达式合法,否则不合法

 public static void main(String[] args) {
        String a = "[a+b*(5-4)]*{x+b+b*({1+2})}";
        System.out.println(chkLegal(a));
    }
    public static boolean chkLegal(String A) {
        Stack<Character> stack = new Stack<>();
        for(int i=0;i<A.length();i++) {
            if(A.charAt(i) == '{'||A.charAt(i) == '[' || A.charAt(i) == '('  ) {
                stack.push(A.charAt(i));
            }
            if(A.charAt(i) == '}'||A.charAt(i) == ']' || A.charAt(i) == ')'  ) {
                stack.pop();
            }
        }
        return stack.isEmpty();
    }

4、List集合排序及去重

使用Collections的sort()方法排序

Collections.sort(intList,new Comparator<Integer>() {

    @Override
    public int compare(Integer o1, Integer o2) {
        // 返回值为int类型,大于0表示正序,小于0表示逆序
        return o2-o1;
    }
});

 使用set集合去重

private List<DeviceServiceLog> removeDuplicateRecord(List<DeviceServiceLog> deviceServiceLogList) {
    Set<DeviceServiceLog> set = new TreeSet<>(new Comparator<DeviceServiceLog>() {

        @Override
        public int compare(DeviceServiceLog o1, DeviceServiceLog o2) {
            return o1.getServiceCode().compareTo(o2.getServiceCode());
        }

    });
    set.addAll(deviceServiceLogList);
    return new ArrayList<>(set);
}

十一、项目

OOA、OOD、OOP区别

OOA是面向对象的分析 Analysis
OOD是面向对象的设计 Design
OOP是面向对象的编程 Programming
都是相辅相成的: 分析是为了设计,设计是为了编程。
都属于软件工程的不同课题。

本文部分知识来源:

互联网侦察---》面试现场---》作者---》channingbreeze 

https://mp.sohu.com/profile?xpt=Z2hfY2Q2YTQ2NzI2YWVmQHNvaHUuY29t&_f=index_pagemp_2&spm=smpc.content.author.3.1555052500338Y1iM07T

Java技术栈       https://www.javastack.cn/

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值