面试总结

Java基础

Synchronized和Lock

Synchronized有三种用法,分别是

  • Synchronized修饰普通实例方法,锁是当前实例对象

  • Synchronized修饰静态方法,锁是当前类的class对象

  • Synchronized修饰代码块,锁是括号里的对象

Lock锁的使用

Lock是jdk1.5引入的一个接口,他的主要实现类有

  • ReenTrantLock():可重入锁,最常用的一种实现类

  • ReentrantReadWriteLock.ReadLock():读锁

  • ReentrantReadWriteLock.WriteLock():写锁

Synchronized和Lock的区别

  1. Synchronized是Java关键字,Lock是Java的一个接口
  2. Synchronized无法判断获取锁的状态,Lock可以判断是否获取到了锁(tryLock())
  3. Synchronized会自动释放锁,Lock必须通过unlock()去手动释放锁
  4. 锁的中断机制不同,Synchronized修饰的线程,其他线程会一直等待,Lock锁的线程,其他线程可能不会一直等待
  5. Synchronized是重入锁,非公平锁,Lock也是可重入锁,默认是非公平锁,但是可以通过在new对象的时候,参数列表指定false,让它成为公平锁
  6. Synchronized适合锁少量的代码同步问题,Lock适合锁大量的同步代码

List集合怎么去重

  1. 利用set去重

    	Set set2 = new HashSet(); 
    	List newList3 = new ArrayList(); 
    	set2.addAll(list);
    	newList3.addAll(set2);
    	System.out.println("set和list转换去重:" + newList3);
    
  2. 遍历后判断,再添加到另一个集合中

    	List newList2 = new ArrayList(); 
    	for (Integer integer : list) { 
    	if(!newList2.contains(integer)){ 
    	newList2.add(integer); 
    	} 
    }
    
  3. 双重for循环去重

     for (int i = 0; i < list.size(); i++) {
         for (int j = 0; j < list.size();j++ ) {
            if (i != j && list.get(i) == list.get(j)) list.remove(j);
        }
    }
    

spring的事务隔离级别和传播行为

spring的事务隔离级别有五个,分别是

  • default: 表示默认使用数据库的事务隔离级别

  • read-unCommit(读未提交):表示其他事务可以看到某个事务修改了但是没有提交的数据,可能造成脏读、幻读、不可重复读

  • read-Commit(读提交):Oracle的默认隔离级别。表示其他事务不能看到某个事务未提交的数据,可以防止脏读,但是不能防止幻读和不可重复读

  • Repeatable-read(可重复读):mysql的默认隔离级别。表示当事务多次读取同一数据时,保证他的值和事务开始的内容是一样的,可以防止脏读,不可重复读,但是可能会出现幻读。

  • Serializable(序列化):这是最可靠但是花费最昂贵的事务隔离级别。可以防止脏读幻读不可重复读。

spring的传播行为有七个,分别是

  1. required:表示如果存在当前事务,就加入,没有就新建一个事务
  2. Mandatory:表示如果存在当前事务,就加入,如果没有,就抛出异常
  3. never:表示以非事务的方式运行,如果存在当前事务,就抛出异常
  4. not-support:表示以非事务的方式运行,如果存在当前事务,就将当前事务挂起
  5. requires-new:表示新建一个事务,如果存在当前事务,就将当前事务挂起
  6. supports:表示支持当前事务,如果不存在当前事务,就以非事务的方式运行
  7. Nested:表示如果存在当前事务,就嵌套在当前事务中运行,如果外层事务失败,会回滚内层事务,但是如果内层事务失败,则不会引起外层事务回滚。如果不存在,就新建一个事务运行

数据库优化

具体场景

  1. 有1000万条数据要插入到数据库中,有什么思路
    首先,如果要将这么多数据插入到数据库中,如果一条一条的插的话,那么这样频繁的开关链接肯定是不行的,如果是这样的话,就可以在一条sql语句中插入多条数据这样可以减少连接次数,然后的话更改了数据的话肯定要提交事务,提交事务的话可以进行分批处理,就是不要每插入一次就提交一下事务,再者就是就是尽量有序插入,这样的话主要是为了减少以后索引的维护压力

  2. 数据库中有1000万条数据库,我要查询比如说a字段为10的,和年龄是10或者15的,讲一下怎么查询

    首先对于查询的字段可以 添加索引,然后的话,使用了索引,就要优化自己的sql语句,不要用到or和in

    可以使用union去把查询的结果并起来,这样的话就不会导致索引不可用。然后对于数据库本身的话也是可以考虑的一方面,可以通过更改数据库引擎,来寻找最优的方式。mysql默认引擎是innoDB,Oracle没有引擎的概念,oracle是将数据处理分为两大类,分别是联机事务处理和联机分析处理。

  3. 一次插入10条数据怎么操作?(Mybatis里面怎么操作)

    可以直接通过insert语句插入,每条字段之间通过“,”隔开。在Mybatis中插入的话,可以通过

    先把要插入的值放进一个lsit集合中,再使用foreach标签来循环遍历这个list集合插入。

索引为什么能提高查询效率

索引本质上是一个数据结构,在Mysql中是B+树,B+树是一种平衡树(一颗空树或者说它左右两颗子树的高度查绝对值不会超过1,并且左右两个子树都是平衡树),在不使用索引时,数据库中的记录都是存储在页中

每个数据页组成了一个双向链表,同时每个数据页中的数据又组成了一个单向链表,所以要查询数据的话,就需要遍历这些链表,因为链表的这个数据结构的特性,自然速度快不了。

当使用的索引后,因为索引底层是一颗平衡树,这个平衡树就像一个"目录",我们可以通过"目录",就能快速的定位到我们要查找的对应记录在具体的哪个页上面,然后再继续通过这个”目录“,可以快速的找到这个页上面的具体记录。(具体是通过平衡树的算法==》二分查找法)

数据库怎么查询重复数据

select * from people where id in (
    select   id  from   people group by   id having count (id)>1)

session执行流程和原理?

  • 用户第一次请求服务器时,服务器端会生成一个sessionid
  • 服务器端将生成的sessionid返回给客户端,通过set-cookie
  • 客户端收到sessionid会将它保存在cookie中,当客户端再次访问服务端时会带上这个sessionid
  • 当服务端再次接收到来自客户端的请求时,会先去检查是否存在sessionid,不存在就新建一个sessionid重复1,2的流程,如果存在就去遍历服务端的session文件,找到与这个sessionid相对应的文件,文件中的键值便是sessionid,值为当前用户的一些信息
  • 此后的请求都会交换这个 Session ID,进行有状态的会话。

session存储的数据存在哪里?

session.setAtturbute()是通过键值对的方式存储数据的,所以底层是存放在键值对里面的

mybatis的#{}和 有 什 么 区 别 ? 为 什 么 {}有什么区别?为什么 {}会存在

mybatis在处理#{}时,会对sql进行预编译,将#{}替换成问号,这样可以有效防止sql注入

mybatis在处理${}时,会直接将我们输入的值进行字符串拼接,所以可能会发生sql注入

但是 既 然 会 存 在 , 那 就 肯 定 会 有 它 的 意 义 , 所 以 说 当 我 们 需 要 s q l 注 入 的 时 候 , 它 就 能 发 挥 它 的 作 用 了 。 比 如 在 我 们 使 用 m y b a t i s 查 询 数 据 时 使 用 o r d e r b y 动 态 参 数 排 序 时 就 应 该 使 用 {}既然会存在,那就肯定会有它的意义,所以说当我们需要sql注入的时候,它就能发挥它的作用了。比如在我们使用mybatis查询数据时使用order by动态参数排序时就应该使用 sql使mybatis使orderby使{}。

mybatis关系映射

数据结构–链表和数组、树

数据结构分为线性结构非线性结构

  • 线性结构
    1. 线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系
    2. 线性结构有两种不同的存储结构,即顺序存储结构链式存储结构,顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的
    3. 链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息
    4. 常见线性结构有:数组、队列、链表和栈
  • 非线性结构
    非线性结构包括:二维数组、多维数组、广义表、树结构、图结构

链表是以节点的形式来存储的,每个节点包含date域,next域:指向下一个节点。链表分为带头节点的链表和没有头节点的链表

finalized()方法

    protected void finalize() throws Throwable {
        try {
            stream.close();
        } catch (IOException e) {
        } finally {
            stream = null;
            super.finalize();
        }
    }

GC负责调用finalize()方法。这个方法不需要程序员手动调用。JVM的垃圾回收期负责调用这个方法。finalize()只需要重写,重写完将来自动有人来调用。

finalize()方法的执行时期:当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法。

前端面试题

如何使用js和jquery设置div的宽和高

JS:

<script type="text/javascript">
var demo = document.getElementById('demo');
demo.style.width = '200px';
demo.style.height = '200px';
</script>

jquery:

$("#div1").css("height","320px");
$("#div1").css("width","480px");

如何隐藏div

通过css:display-none

将div的宽度和高度设置为0

opacity来设置不透明级别,设置为透明的

js有哪些数据类型

值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Object类型

springboot和springmvc的区别

在了解两个东西或者是两个技术的区别时,首先得知道他们是什么,对于springmvc来说,根据官方文档的解释,springmvc是一个基于servlet API搭建的原始web框架,属于springweb模块的一部分,而springboot是spring发展到一定程度的产物。它可以说是一个全新的框架,也可以说是一种新的编码规范,springboot的产生,简化了框架的使用,“约定大于配置”,是springboot的宗旨,我们不需要在使用spring众多框架时,去配置大量而繁琐的配置文件了,只需要使用约定好的注解。

对于springboot和springmvc的区别

首先,

  1. springmvc是基于spring的一个mvc框架,主要为了简化web应用的开发。springboot实现了自动配置,降低了项目搭建的复杂度
  2. springmvc要自己配置web服务器启动,springboot内置了web服务器,不需要自己配置
  3. springmvc需要在web.xml中注册前端控制器和编写springmvc配置文件,而springboot不需要任何配置文件

spring的JDBC和Java原生态的JDBC有什么区别

spring的JDBC是对Java原生态JDBC进行了简单的封装,我们在spring中使用jdbc,只需要关注sql语句编写和返回的结果集就好了,像连接的创建和关闭,不用我们自己去管理,spring帮我们完成(通过IOC)

Redis缓存的理解

Redis是一个开源的,基于key-value的数据结构存储系统,支持多种类型的数据结构,比如String、数组、list、set、map。

Redis的缓存是存放在内存中的,可以通过设置一个定时器,定时将缓存中的数据进行持久化

mybatis的执行流程(工作原理)

//        1.加载配置文件  通过InputStream
        InputStream is = Resources.getResourceAsStream("mybatis.xml");
//        2.创建sqlSession工厂
        SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);
//        3.创建sqlSession
        SqlSession session = sf.openSession();
//        4.创建mapper接口对象 动态生成mapper接口实现类
        DeptMapper mapper = session.getMapper(DeptMapper.class);
//        5.利用mapper对象进行持久化操作
        Dept dept = mapper.selectByPrimaryKey("30");
        System.out.println(dept);
//        6.关闭资源
        session.close();
  1. 首先通过Resources去加载配置文件,返回一个io流
  2. 创建sqlSession
  3. 创建sqlSession
  4. 通过sqlSession调用mapper接口对象(通过Java反射机制)
  5. 利用mapper对象进行持久化操作
  6. 关闭资源

mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式

通过Java的反射机制创建对象,同时使用反射给对象的属性逐一赋值并返回,哪些关联不到映射关系的对象是无法赋值的,所以会返回null。

可以使用resultMap标签逐一定义列名和对象属性名之间的映射关系,第二种就是使用sql列起别名的方式

Mybatis映射文件中,如果A标签通过include引用了B标签的内容,那么B标签能否定义在A标签的后面,还是说必须定义在A标签的前面?

虽然Mybatis解析xml文件是按顺序解析的,但是被引用的B标签还是可以被定义在任何地方,Mybatis都能够正确识别

原理是,Mybatis在解析A标签的时候,如果发现引用了B标签,但是B标签还没有解析到,那么这个时候Mybatis会将A标签标记为未解析状态,然后继续往下解析其他内容,当所有标签解析完毕,Mybatis会重新解析那么被标记为未解析状态的标签。

笔试题

文件复制

//        指定文件要复制的文件
        File file = new File("F:\\test1\\output.txt");
//        复制到哪里
        File target = new File("F:\\test1\\copy1.txt");
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
//            输入流
            fis = new FileInputStream(file);
//            输出流
            fos = new FileOutputStream(target);
//            指定一个byte数组,读取一个字节数组长度和写出一个字节数组长度
            byte[] bytes = new byte[1024];
//            read方法读到末尾会返回-1
            int len =0 ;
            while ((len = fis.read(bytes))!=-1){
//                写入指定文件中
                fos.write(bytes);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally { 
            try { 
                if (fos!=null)fos.close();
                if (fis!=null)  fis.close(); 
            } catch (IOException e) { 
                e.printStackTrace();
            }
        }

单例模式

//懒汉式实现单例模式
public class SingleTon {
    private SingleTon(){}
    public static SingleTon s;
    public static synchronized SingleTon getInstance(){
        if (s==null){
            s = new SingleTon();
        }
        return s;
    }
}
//饿汉式实现单例模式
public class SingleTon {
    private SingleTon(){}
    public static SingleTon s = new SingleTon();
    public static SingleTon getInstance(){
        return s;
    }
}

排序算法

冒泡排序

for (int i = 0; i < arr.length-1; i++) {
     for (int j = 0; j < arr.length-i-1; j++) {
         if (arr[j]>arr[j+1]){
             arr[j] = arr[j]+arr[j+1];
             arr[j+1] = arr[j]-arr[j+1];
             arr[j] = arr[j]-arr[j+1];
    }
  }
}
        System.out.println(Arrays.toString(arr));

选择排序

        for (int i = 0; i < arr.length-1; i++) {
            for (int j = i; j < arr.length-1; j++) {
                if (arr[i]>arr[j+1]){
                    arr[i] = arr[i] + arr[j+1];
                    arr[j+1] = arr[i] - arr[j+1];
                    arr[i] = arr[i] - arr[j+1];
                }
            }
        }
        System.out.println(Arrays.toString(arr));

插入排序

for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0; j--) {
                if (arr[j]<arr[j-1]){
                    arr[j] = arr[j]^arr[j-1];
                    arr[j-1] = arr[j]^arr[j-1];
                    arr[j] = arr[j]^arr[j-1];
                }
            }

        }
        System.out.println(Arrays.toString(arr));

快速排序

二分查找

 int[] arr = {10,20,30,40,50,60,70,80};
        int target = 30;//目标值
        int min = 0;//最小值0
        int max = arr.length;//最大值:数组长度
        while(min<max){//
            int mid = (min + max)/2;//中间值
            if (arr[mid] < target){
                min = mid;
            }
            if (arr[mid] > target){
                max = mid-1;
            }
            if (arr[mid] == target){
                System.out.println(mid);
                break;
            }

        }

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值