新增面试题

目录

1.反射代码

2.冒泡排序

3、单例工厂

4、二分查找算法

5、集合的遍历方式

6、怎么跨域请求:

7、事务的最高权限可以限制到具体的方法还是类

8、数据库的内链接外链接

9、数据库怎么储存数据

10、一条查询语句中包含所有的子句,那么各子句之间的执行顺序?(面)

11、sql语句的优化

12、消息队列

13、数据库的还原和备份

14线程等待的区别

15、lombok的使用需要在IDE中提前安装插件!!!,如果项目在Linux系统中部署发布.是否需要提前安装插件!!!

16、Spring容器如何理解


1.反射代码


2.冒泡排序

package cn.tedu.array;

import java.util.Arrays;

/**本类用来完成冒泡排序*/
public class TestBubbleSort {
	public static void main(String[] args) {
		//1.创建一个无序的数组
		int[] a = {27,96,73,25,21};
		//2.调用method()完成排序
		int[] newA = method(a);
		System.out.println("排序完毕:"+Arrays.toString(newA));
	}
	public static int[] method(int[] a) {
		//1.外层循环,控制比较的轮数,假设有n个数,最多比较n-1次
		//开始值:1 结束值:<= a.length-1 变化:++
		//控制的是循环执行的次数,比如5个数,最多比较4轮,<= a.length-1,最多取到4,也就是[1,4]4次
		for(int i = 1 ; i <= a.length-1 ; i++) {
			System.out.println("第"+i+"轮:");
			//2.内层循环:相邻比较+互换位置
			for(int j=0; j < a.length-i ; j++) {
				//相邻比较,a[j]代表的就是前一个元素,a[j+1]代表的就是后一个元素
				if(a[j] > a[j+1]) {
					//交换数据
					int t = a[j];
					a[j] = a[j+1];
					a[j+1] = t;
					//System.out.println("第"+(j+1)+"次比较交换后:"+Arrays.toString(a));
				}
			}
			System.out.println("第"+i+"轮的结果:"+Arrays.toString(a));
		}
		return a;//把排序好的数组a返回
	}
}

3、单例工厂


    方案一:饿汉式
    1)把本类的构造方法私有化–为了不让外界调用构造函数来创建对象
    2)通过本类的构造方法创建对象,并把这个对象也私有化,为了防止外界调用
    3)提供公共的全局访问点向外界返回本类的唯一的一个对象
    注意:公共方法需要设置成静态–需要跳过对象,通过类名直接调用这个返回本类对象的公共方法
    对象也需要设置成静态的–这个对象需要在静态方法中被返回,而静态只能调用静态
    方案二:懒汉式
    ==延迟加载的思想:==我们有的时候有些资源并不是需要第一时间就创建出来,所以需要延迟到需要时再创建
    这样既可以提升性能,又可以节省资源
    1)把本类的构造方法私有化–为了不让外界调用构造函数来创建对象
    2)创建了一个本类类型的引用类型变量【这个变量后续用来保存创建出来的对象的地址值】
    3)提供公共的全局访问点向外界返回本类的唯一的一个对象

4、二分查找算法


    

//二分查找测试类
//注意:二分查找必须用在有序列表中进行二分查找
 public class BinaryChopTest {
    public static void main(String[] args) {
    int[] arrays = {1, 6, 10, 11, 12, 100};
    for (int i = 0; i <= 10; i++) {
    int sign = recursionBinarySearch(arrays, i, 0, arrays.length - 1);
        if (sign == -1) {
        System.out.println("在数组中找不到" + i + "这个元素");
        System.out.println("目标元素" + i + "在数组的第" + sign + "位置");
        }
        sign = -1;
    }
}
 /**
 * 使用二分查找和递归的结合进行查找
 * 时间复杂度:O(logN)
 * @param arrays    有序数组
 * @param target    要查找的元素(目标元素)
 * @param low        最低位
 * @param high        最高位
 * @return         找到的位置    
 */
public static int recursionBinarySearch(int[] arrays, int target, int low, int high){
    if (target < arrays[low] || target > arrays[high] || low > high) {
        return -1;
        }
        int middle = (low + high) / 2; //初始化中间位置的值
        if (arrays[middle] > target) {
            return recursionBinarySearch(arrays, target, low, middle - 1);
            } else if (arrays[middle] < target) {
            return recursionBinarySearch(arrays, target, middle + 1, high);
            } else {
            return middle;
            }
        }
    } 

   

5、集合的遍历方式


    方式一:使用普通for循环,size()和get(int index)结合。【只能操作list集合】
        ArrayList list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        for(int i = 0; i < list.size(); i++){
           System.out.println(list.get(i));
        }
    方式二:使用普通for,toArray()方法先将集合转为数组,然后遍历数组。【能操作所有的单列集合】
        Collection c = new ArrayList();  // 多态,父类引用指向子类对象
        c.add("a");  // 添加元素
        c.add("b");
        c.add("c");
        Object[] objs = c.toArray();  // 将集合转换为数组
        for(int i = 0; i < objs.length; i++){  // 遍历数组
            System.out.println(objs[i]);
        }
    方式三:迭代器遍历,Iterator()获取到迭代器,然后通过迭代器的方法获取。
        // 创建集合对象
        Collection c = new ArrayList();
        c.add("a");  // 添加元素
        c.add("b");
        c.add("c");
        // 获取迭代器对象
        Iterator it = c.iterator();  // 多态,实际上获取的是Iterator的实现类对象
        While(it.hasNext()) {  // boolean hasNext():判断是否有元素可以获取,没有就结束循环,用于循环结束的条件
            System.out.println(it.next());  // Objext next():返回下一个元素
        }
    方式四:列表迭代器遍历,listIterator()先获取到列表迭代器,然后通过列表迭代器的方法【只适用于list集合】
        // 创建集合对象
        ArrayList list = new ArrayList();
        // 添加元素
        list.add("a");
        list.add("b");
        list.add("c");
        // 获取列表迭代器
        ListIterator lit = list.listIterator();
        // 循环获取到每一个元素
        while(lit.hasNext()){  // boolean hasNext():判断是否有元素可以获取,没有就结束循环
            System.out.println(lit.Next());  // E next():获取元素
        }
    方式五:增强for -->快捷键:fore 按  alt + /;
        // 创建集合对象
        Collection<String> c = new ArrayList<String>();  //父类引用指向子类对象
        c.add("a");
        c.add("b");
        c.add("c");
        // 增强for循环遍历集合
        for(String s : c){   //增强for遍历集合底层使用的是迭代器,不能对集合中的元素进行增删操作
            System.out.println(s);
        }
    通过两种方法遍历上题中的map集合
        package work;

        import java.util.HashMap;
        import java.util.Map;
        import java.util.Map.Entry;
        import java.util.Set;

        /*        
         *         依次获取每个键值对的键和值
         *             Set<T> keySet
         *             
         *             Set<Map.Entry<K,V>> entrySet()
         *                 getKey
         *                 getValue
         */
        public class Work02_TraversalMap {
            public static void main(String[] args) {
                Map<String,Integer> hashMap = new HashMap<String,Integer>();
                hashMap.put("张三", 41);
                hashMap.put("李四", 24);
                hashMap.put("王五", 19);
                hashMap.put("秦六", 26);
                //遍历方式一
                Set<String> keys = hashMap.keySet();
                for(String key:keys) {
                    System.out.println(key + hashMap.get(key));
                }
        
                System.out.println("---------------------");
                //遍历方式二
                Set<HashMap.Entry<String, Integer>> entry = hashMap.entrySet();
                for(HashMap.Entry<String,Integer> en:entry) {
                    System.out.println(en.getKey() + " : " + en.getValue());
                }
            }
        }

6、怎么跨域请求:


    1.添加跨域注解
    2.使用jsp技术

7、事务的最高权限可以限制到具体的方法还是类


    Spring事务注解是个典型的Spring AOP的注解。方法上面加上@Transactional,方法就有了事务的能力。

8、数据库的内链接外链接


    内链接又叫等值连接:就是求两个表相同的部分;内连接:在每个表中找出符合条件的共有记录。[x inner join y on...]
    外连接:左连接,右连接和全连接。
    左连接的应用实例:根据左表的记录,在被连接的右表中找出符合条件的记录与之匹配,如果找不到与左表匹配的,用null表示
        Select * from tableA  left join tableB On tableA.column1=tableB.column2;
    右连接:根据右表的记录,在被连接的左表中找出符合条件的记录与之匹配,如果找不到匹配的,用null填充。[x right [outer] join y on...]
        Select * from tableA right  join  tableB On tableA.column1=tableB.column2
    全连接:返回符合条件的所有表的记录,没有与之匹配的,用null表示(结果是左连接和右连接的并集)
        第一种写法:(full join .. on ..)
    自连接:MySQL数据库中不提供全连接,可用left join和right join将两张表的数据取出,再用union去重。
        语法:Select * from tableA  left join tableB On table A.column1 = tableB.column1
            Union
        Select * from tableA right join tableB On tableA.column1 = tableB.column1;

9、数据库怎么储存数据


    行和列储存数据
    前端传给后台数据,后台需要保存到数据库中,数据保存分为更新和新增,这两种操作的实现方法又是不一样的。
    那么一般有两种方法来实现数据保存:
    1.dao层或者是facade层,直接Delete(remove)改该数据表,再insert(persist)数据。
    2.根据传入的数据进行分类,是新增的、更新的还是已经不存在的,在分别进行新增、更新或者是删除操作。
    这种方法的实现,一般是4个list,一个放从后台查询的lists全部数据,其他三个分别为insertList、updateList和deleteList。
    通过关键字,在lists中没有记录的关键字放入insertList中,其他的也是按照关键字

10、一条查询语句中包含所有的子句,那么各子句之间的执行顺序?(面)


    FROM-->WHERE(过滤条件)-->GROUP BY(分组)-->HAVING(过滤条件)-->SELECT(查询)-->ORDER BY(排序)-->limit(分页)

11、sql语句的优化


    1.避免Select *
    Selcet中每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。
    1)尽量避免select * 的存在,使用具体的列代替*,避免多余的列
    2)使用where限定具体要查询的数据,避免多余的行
    3)使用top,distinct关键字减少多余重复的行
    4. insert插入优化
    分析说明:insert into select批量插入,明显提升效率,可以尽量避免一个个循环插入。
    5. 优化修改删除语句
    如果你同时修改或删除过多数据,会造成cpu利用率过高从而影响别人对数据库的访问。如果采用单一循环操作,效率会更低。折中的办法就是,分批操作数据。
    6.避免全表扫描
    在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,
    就会造成优化器删去索引而使用全表扫描。
    Where中少用NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE,它们会引起全表扫描。避免使用like和or语句。
     7.sql语句用大写的;因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行。
    8.用Where子句替代having子句

12、消息队列


    1.消息队列使用的场景和中间件有很多,但解决的核心问题主要是:异步、解耦、消峰填谷。
    2.缺点主要在于系统的可用性、复杂性、一致性问题,引入消息队列后,需要考虑MQ的可用性,万一MQ崩溃了岂不是要爆炸?
    而且复杂性明显提高了,需要考虑一些消息队列的常见问题和解决方案,还有就是一致性问题,一条消息由多个消费者消费,
    万一有一个消费者消费失败了,就会导致数据不一致。
    3.RabbitMQ有三种模式:单机模式,普通集群模式,镜像集群模式
    镜像集群模式是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,
    无论元数据还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,
    都会自动把消息到多个实例的queue里进行消息同步。
    优点在于你任何一个实例宕机了,没事儿,别的实例都可以用。
    缺点在于性能开销太大和扩展性很低,同步所有实例,这会导致网络带宽和压力很重,而且扩展性很低,
    每增加一个实例都会去包含已有的queue的所有数据,并没有办法线性扩展queue。
    开启镜像集群模式可以去RabbitMQ的管理控制台去增加一个策略,指定要求数据同步到所有节点的,
    也可以要求就同步到指定数量的节点,然后你再次创建queue的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。

13、数据库的还原和备份


    数据库导入和导出
    导出数据库: 将mysql中的数据库以 xxx.sql文件进行转储.
    导入数据库: 读取xxx.sql文件 之后工具执行其中的sql,最终实现数据的导入功能.
    说明: 上述的操作称之为数据库冷备份. 一般在生产环境下 为了保证数据的安全.一般都会定期冷备份.(周期3-7天左右) 一般一式3份. 数据库的冷备份是恢复数据最后有效的手段.
    特点: 冷备份容易丢失数据. 热备份可以实现实时备份.

14线程等待的区别


    sleep是Thread类中的方法,wait是Object类的方法,
    sleep不会释放对象锁,wait会释放对象锁。
    sleep可以在任何地方用,wait()只能在synchronized方法或块中使用。
    sleep一定要传入参数,wait不传参数的时候是进入无限等侍,要使用notife才能唤醒。


15、lombok的使用需要在IDE中提前安装插件!!!,如果项目在Linux系统中部署发布.是否需要提前安装插件!!!


    答案: 不要!!!
    原因: lombok插件编译期有效.(编译期:由xxx.java文件编译为xxxx.class文件).在打包之前class文件中已经包含了set/get等方法,所以项目打包之后可以直接运行.无需安装插件!!!.

16、Spring容器如何理解


    4.2.1 关于IOC的说明
    IOC: 控制反转
    具体含义: 将对象创建的权利交给Spring容器管理.
    原因: 如果将对象自己管理,则必然出现耦合性高的现象. 不方便扩展
    容器: 是一种数据结构类型 Map<K,V>集合
    KEY: 类名首字母小写
    Value: Spring为当前的类创建的对象.
    只要程序启动成功,则Map集合中(容器),里边包含了所有的IOC管理的对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值