2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经

2023春招上海亿保健康科技集团有限公司.社招.一面面经

  • 公司简介
  • 面试官问题
    • 1.介绍一下MySql的索引
    • 2.介绍一下聚簇(聚集)索引和非聚簇(非聚集)索引
    • 3.介绍一下项目的技术难点
    • 4. 项目是否用过设计模式
    • 5.JVM调优的经验

公司简介

2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第1张图片

面试官问题

1.介绍一下MySql的索引

定义:索引是帮助MySQL高效获取数据的排好序数据结构

索引的数据结构:
二叉树
红黑树
Hash表
B-Tree

  • 二叉树
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第2张图片
    如果查询的元素是自增,都放到了右子树上,比如查询7这个结点,我们就需要查询6次,而且是线性结构,所以不适合。

  • 红黑树
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第3张图片
    如果需要查询的数据是叶子结点上的数据,而且数据量很大的情况,其查询效率不稳定,其次红黑树在插入数据的时候,也是会按照规则进行旋转,其查询的效率不稳定,所以不合适

  • Hash表
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第4张图片
    无法进行范围查找。

  • B树
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第5张图片
    B树叶子结点和非叶子结点都存储数据,查询效率不稳定。其次,同B+树比较,相同的磁盘空间,B树非叶子结点存放了数据,那么其能存放的结点数量相比B+树来说会少。

  • B+树
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第6张图片
    非叶子结点只存放索引,叶子结点存放索引和数据这样就使得B+树的查询效率更加稳定,均为从根结点到叶子结点的路径。横向看,同一高度的叶子结点依次递增,方便范围查找。
    页结点默认大小:16KB
    示例:以bigint为例,占8字节,空白占6字节,那么一个页结点中一共可以存储1170个索引。
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第7张图片

2.介绍一下聚簇(聚集)索引和非聚簇(非聚集)索引

  • Myisam
    在这里插入图片描述
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第8张图片
    MYI结尾文件中,叶子结点存放的是磁盘文件的地址,指向存储的数据。
    MyIsam的索引就是非聚簇索引,其索引和数据文件是分开的。

  • Innodb
    在这里插入图片描述
    2023春招上海亿保健康科技集团有限公司.社招.Java后端一面面经_第9张图片
    innodb中主键索引就是聚集索引,其叶子结点保存了完整的数据记录。
    innodb中普通索引就是非聚簇索引,其叶子结点中保存的是其对应的主键。

回表:普通索引查询方式,需要先查询普通索引树,得到其对应的主键值为3,再到主键索引树搜索一次,这个过程称为回表。

3.介绍一下项目的技术难点

4. 项目是否用过设计模式

创建者模式:单例模式

  • 饿汉式 :线程安全
public class HungerManClass {
    private String name;
    // 1.创建私有的构造器
    // 这里private原因;不想外部创建对象
    private HungerManClass(String s){
        this.name = name;
        System.out.println(s);
    }
    // 2.在类的内部初始化对象,并且需要将其修饰为static
    // 这里访问修饰符随意,可以是任意一个,因为本身只是当前类内创建对象
    // 这里static的原因是下面的getInstance()方法是static的,静态方法调用静态对象
    private static HungerManClass hungerManClass = new HungerManClass("饿汉式");


    // 3.向外暴露一个静态的公共方法。getInstance
    // 这里static是因为getInstance()作为给外部提供的方法,在构造器不能被外部使用的情况下,想到了用类名.方法名就能调用的静态方法
    public static HungerManClass newInstance() {
        return hungerManClass;
    }
}

调用

public class TestH {
    @Test
    public void testHunger() {
        HungerManClass hungerManClass = HungerManClass.newInstance();
        System.out.println(hungerManClass);
    }
}

输出

饿汉式
com.SingleModle.hunger.HungerManClass@2e817b38
  • 懒汉式:线程不安全
/**
 * @author wty
 * @date 2023/2/22 14:53
 */
public class LazyManClass {
    private String name;

    // 1.私有化构造器,这里private后,外部不允许再创建对象
    private LazyManClass(String name){
        this.name = name;
        System.out.println(name);
    }

    // 2.创建对象,但是不new
    private static LazyManClass lazyManClass = null;

    // 3.写getInstance方法,用static修饰
    public static LazyManClass newInstance() {

        // 这里判断一下,如果对象没有创建那么就创建一个对象
        if (lazyManClass == null){

            lazyManClass = new LazyManClass("懒汉式");
        }
        // 如果对象已经创建过了,那么直接返回即可
        return lazyManClass;
    }
}

测试类

public class TestLazyClass {
    @Test
    public void testLazy(){
        LazyManClass lazyManClass = LazyManClass.newInstance();
        System.out.println(lazyManClass);
    }
}

输出结果

懒汉式
com.SingleModle.lazy.LazyManClass@2e817b38

但是上述方式是线程不安全的,因此我们的做法如下:

package com.SingleModle.lazy;

/**多线程环境下的懒汉式单例模式,(双检锁+volatile实现)
 * @author wty
 * @date 2023/2/22 15:00
 */
public class LazyManSafe {
    private String name;

    // 1.私有化构造器,这里private后,外部不允许再创建对象
    private LazyManSafe(String name){
        this.name = name;
        System.out.println(name);
    }

    // 2.创建对象,但是不new
    private static volatile LazyManSafe lazyManSafe = null;

    // 3.写getInstance方法,用static修饰
    public static LazyManSafe newInstance() {

        // 这里判断一下,如果对象没有创建那么就创建一个对象
        if (lazyManSafe == null){
            synchronized (LazyManClass.class){
                if (lazyManSafe == null){
                    lazyManSafe = new LazyManSafe("懒汉式");
                }
            }
        }
        // 如果对象已经创建过了,那么直接返回即可
        return lazyManSafe;

    }

}

  • 工厂模式
    见我另一篇文章
    工厂模式详解

5.JVM调优的经验

你可能感兴趣的:(面经,春招,Java后端)