首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >百度校招 Java 开发岗与 java 架构师历年经典面试题汇总

百度校招 Java 开发岗与 java 架构师历年经典面试题汇总

原创
作者头像
啦啦啦191
发布2025-07-04 13:31:52
发布2025-07-04 13:31:52
1760
举报
文章被收录于专栏:Java开发Java开发

以下是百度校招Java开发岗和Java架构师的部分面试题及答案:

Java开发岗

  • Hashmap如何变线程安全,每种方式的优缺点?
    • 使用Collections.synchronizedMap():优点是实现简单,直接调用工具方法即可。缺点是效率相对较低,因为其内部是通过 synchronized 关键字实现同步,整个Map的操作都被锁控制,并发度不高。
    • 使用ConcurrentHashMap:优点是性能高,采用分段锁机制,允许多个线程同时访问不同的分段,并发性能好。缺点是相比HashMap实现更复杂,占用内存可能稍多。
  • 服务器如何负载均衡,有哪些算法,哪个比较好?一致性哈希原理是什么,怎么避免DDOS攻击请求打到少数机器?
    • 负载均衡算法:常见的有轮询算法、加权轮询算法、随机算法、最少连接数算法等。轮询算法简单公平,但未考虑服务器性能差异;加权轮询可根据服务器性能分配请求,更合理;随机算法具有随机性;最少连接数算法将请求分配给连接数最少的服务器,能更好地利用服务器资源。
    • 一致性哈希原理:将服务器节点映射到一个0 - 2^32的哈希环上,请求根据其键值哈希后也映射到环上,然后按顺时针方向找到离它最近的服务器节点处理请求。
    • 避免DDOS攻击:可通过部署防火墙、设置访问频率限制、使用CDN(内容分发网络)等方式,CDN可将请求分散到多个节点,防火墙和访问频率限制能过滤掉异常高频请求,减少目标服务器压力。
  • Redis的持久化怎么做,aof和rdb有什么区别,各自优缺点是什么?
    • RDB:优点是生成的快照文件紧凑,占用空间小,恢复数据速度快。缺点是可能会丢失最后一次快照之后到故障发生期间的数据,且生成快照时可能会阻塞主线程。
    • AOF:优点是数据安全性高,能记录每一个写操作,最多只丢失一个命令的数据。缺点是文件体积较大,恢复数据时需要重放所有写命令,速度相对较慢,且可能存在日志文件过大需要定期重写的情况。

Java架构师

  • JMM(主内存、工作内存、happens - before)是什么?
    • JMM即Java内存模型,定义了线程和主内存之间的交互规则。主内存是所有线程共享的内存区域,存储了对象实例等数据。工作内存是每个线程私有的,线程对变量的操作先在工作内存中进行,然后再同步到主内存。happens - before是JMM中的一个重要概念,用于定义操作之间的先后顺序,保证内存可见性和有序性,若A happens - before B,则A操作的结果对B可见,且A的操作顺序排在B之前。
  • 有哪些无锁数据结构?无锁实现的原理是什么?
    • 无锁数据结构:常见的有ConcurrentHashMap(部分操作无锁)、乐观锁实现的容器等。
    • 原理:主要基于CAS(Compare - And - Swap)操作,它是一种原子操作,通过比较内存中的值和预期值,如果相等则进行更新,无需加锁就能实现多线程对数据的并发访问,提高了并发性能。
  • MySQL怎么优化table scan?
    • 添加合适索引:分析查询语句,对经常用于条件过滤、连接条件的列添加索引,但要避免过多索引导致更新性能下降。
    • 优化查询语句:尽量明确查询条件,避免使用SELECT *,只查询需要的列,减少数据扫描量。
    • 分区表:如果表数据量很大,可根据某些规则(如时间、地域等)将表分区,查询时只扫描相关分区,减少扫描范围。
    • 优化表结构:合理设计字段类型,避免使用过大的字段类型,减少数据存储量,从而降低扫描成本。

其他面试题答案如下:

  • 红黑树的插入时间复杂度:红黑树是一种自平衡的二叉查找树,插入一个新节点后,可能会破坏红黑树的性质,需通过旋转和重新着色来恢复平衡,插入的时间复杂度为O(logn)。
  • 解决哈希冲突的方式:常见的有链地址法(HashMap采用)、开放定址法(包括线性探测、二次探测等)、再哈希法、建立公共溢出区等。
  • G1什么时候引发Full GC:堆内存不足、晋升失败(新生代对象晋升到老年代时,老年代空间不足)、元空间不足等情况可能会引发G1的Full GC。
  • TCP握手挥手过程及其状态转换:三次握手过程为客户端发送SYN包进入SYN_SENT状态,服务器接收后回复SYN + ACK包进入SYN_RCVD状态,客户端再发送ACK包进入ESTABLISHED状态,服务器也进入ESTABLISHED状态。四次挥手过程为客户端发送FIN包进入FIN_WAIT_1状态,服务器接收后回复ACK包进入CLOSE_WAIT状态,客户端收到ACK后进入FIN_WAIT_2状态,服务器发送FIN包进入LAST_ACK状态,客户端接收FIN后回复ACK并进入TIME_WAIT状态,服务器收到ACK后进入CLOSED状态,客户端等待2MSL后也进入CLOSED状态。

百度校招Java开发岗历年经典面试题汇总(实操篇)

一、Java基础

1.1 JDK和JRE的区别

实操场景:验证JDK和JRE的安装与区别

代码语言:bash
复制
# 检查JDK版本
java -version
javac -version

# 查看JDK安装路径
which java
which javac

# 验证JRE是否包含编译器
# 尝试在仅安装JRE的环境中执行javac命令,会提示"command not found"

1.2 ==和equals的区别

代码示例

代码语言:java
复制
public class EqualsDemo {
    public static void main(String[] args) {
        // 基本类型比较
        int a = 10;
        int b = 10;
        System.out.println("基本类型比较: " + (a == b)); // true

        // 引用类型比较
        String str1 = new String("hello");
        String str2 = new String("hello");
        System.out.println("引用地址比较: " + (str1 == str2)); // false
        System.out.println("值比较: " + str1.equals(str2)); // true

        // 字符串常量池比较
        String str3 = "world";
        String str4 = "world";
        System.out.println("常量池引用比较: " + (str3 == str4)); // true
    }
}

1.3 final的作用

代码示例

代码语言:java
复制
// 1. final类不能被继承
final class FinalClass {
    public void print() {
        System.out.println("Final Class");
    }
}

// 2. final方法不能被重写
class Parent {
    public final void finalMethod() {
        System.out.println("Final Method");
    }
}

class Child extends Parent {
    // 以下代码会编译错误,无法重写final方法
    // public void finalMethod() {}
}

// 3. final变量必须初始化且不可修改
class FinalVariableDemo {
    final int MAX_COUNT = 100;
    final String NAME;

    public FinalVariableDemo(String name) {
        this.NAME = name; // 必须在构造函数中初始化
    }

    public void test() {
        // MAX_COUNT = 200; // 编译错误,无法修改final变量
    }
}

1.4 String相关问题

实操场景:性能对比测试(String vs StringBuilder)

代码语言:java
复制
public class StringPerformanceTest {
    public static void main(String[] args) {
        int loopCount = 10000;

        // 使用String拼接
        long startTime = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < loopCount; i++) {
            str += i;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("String拼接耗时: " + (endTime - startTime) + "ms");

        // 使用StringBuilder拼接
        startTime = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < loopCount; i++) {
            sb.append(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder拼接耗时: " + (endTime - startTime) + "ms");
    }
}

1.5 抽象类与接口

代码示例:实现多继承特性

代码语言:java
复制
// 接口定义
interface Flyable {
    void fly();
}

interface Swimmable {
    void swim();
}

// 抽象类定义
abstract class Animal {
    abstract void eat();
}

// 实现类
class Duck extends Animal implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("鸭子会飞");
    }

    @Override
    public void swim() {
        System.out.println("鸭子会游泳");
    }

    @Override
    void eat() {
        System.out.println("鸭子吃水草");
    }
}

1.6 Java中IO流

实操场景:文件复制工具实现

代码语言:java
复制
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileCopyDemo {
    public static void main(String[] args) {
        String sourceFile = "source.txt";
        String targetFile = "target.txt";

        // 1. 使用传统字节流
        try (InputStream is = new FileInputStream(sourceFile);
             OutputStream os = new FileOutputStream(targetFile)) {
            
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            System.out.println("传统字节流复制完成");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 2. 使用NIO.2 Files工具类
        try {
            Path sourcePath = Paths.get(sourceFile);
            Path targetPath = Paths.get(targetFile);
            Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("NIO.2复制完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

1.7 Files的常用方法

代码示例:文件操作工具类

代码语言:java
复制
import java.io.IOException;
import java.nio.file.*;
import java.util.List;

public class FileUtils {
    // 检查文件是否存在
    public static boolean checkFileExists(String filePath) {
        Path path = Paths.get(filePath);
        return Files.exists(path);
    }

    // 创建新文件
    public static void createFile(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        Files.createFile(path);
    }

    // 创建目录
    public static void createDirectory(String dirPath) throws IOException {
        Path path = Paths.get(dirPath);
        Files.createDirectories(path);
    }

    // 删除文件或目录
    public static void delete(String path) throws IOException {
        Files.deleteIfExists(Paths.get(path));
    }

    // 复制文件
    public static void copy(String source, String target) throws IOException {
        Path sourcePath = Paths.get(source);
        Path targetPath = Paths.get(target);
        Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
    }

    // 移动文件
    public static void move(String source, String target) throws IOException {
        Path sourcePath = Paths.get(source);
        Path targetPath = Paths.get(target);
        Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
    }

    // 读取文件内容
    public static List<String> readAllLines(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        return Files.readAllLines(path);
    }

    // 写入文件内容
    public static void writeLines(String filePath, List<String> lines) throws IOException {
        Path path = Paths.get(filePath);
        Files.write(path, lines);
    }
}

二、容器

2.1 Java容器有哪些

实操场景:容器性能对比测试

代码语言:java
复制
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ContainerPerformanceTest {
    public static void main(String[] args) {
        int loopCount = 100000;

        // 测试ArrayList
        testList(new ArrayList<>(), loopCount);

        // 测试LinkedList
        testList(new LinkedList<>(), loopCount);

        // 测试HashMap
        testMap(new HashMap<>(), loopCount);

        // 测试ConcurrentHashMap
        testMap(new ConcurrentHashMap<>(), loopCount);
    }

    private static void testList(List<Integer> list, int count) {
        long startTime = System.currentTimeMillis();

        // 添加元素
        for (int i = 0; i < count; i++) {
            list.add(i);
        }

        // 随机访问元素
        for (int i = 0; i < count; i++) {
            list.get(i);
        }

        long endTime = System.currentTimeMillis();
        System.out.println(list.getClass().getSimpleName() + "耗时: " + (endTime - startTime) + "ms");
    }

    private static void testMap(Map<Integer, Integer> map, int count) {
        long startTime = System.currentTimeMillis();

        // 添加元素
        for (int i = 0; i < count; i++) {
            map.put(i, i);
        }

        // 随机访问元素
        for (int i = 0; i < count; i++) {
            map.get(i);
        }

        long endTime = System.currentTimeMillis();
        System.out.println(map.getClass().getSimpleName() + "耗时: " + (endTime - startTime) + "ms");
    }
}

2.2 HashMap相关问题

实操场景:自定义HashMap实现

代码语言:java
复制
import java.util.LinkedList;

public class CustomHashMap<K, V> {
    private static final int DEFAULT_CAPACITY = 16;
    private LinkedList<Entry<K, V>>[] table;

    public CustomHashMap() {
        table = new LinkedList[DEFAULT_CAPACITY];
        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
            table[i] = new LinkedList<>();
        }
    }

    public void put(K key, V value) {
        int index = getIndex(key);
        LinkedList<Entry<K, V>> bucket = table[index];

        // 检查是否已存在相同key
        for (Entry<K, V> entry : bucket) {
            if (entry.key.equals(key)) {
                entry.value = value;
                return;
            }
        }

        // 添加新元素
        bucket.add(new Entry<>(key, value));
    }

    public V get(K key) {
        int index = getIndex(key);
        LinkedList<Entry<K, V>> bucket = table[index];

        for (Entry<K, V> entry : bucket) {
            if (entry.key.equals(key)) {
                return entry.value;
            }
        }

        return null;
    }

    private int getIndex(K key) {
        return Math.abs(key.hashCode()) % DEFAULT_CAPACITY;
    }

    static class Entry<K, V> {
        K key;
        V value;

        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }
}

2.3 ConcurrentHashMap相关问题

实操场景:多线程环境下的并发操作

代码语言:java
复制
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ConcurrentHashMapDemo {
    private static final int THREAD_COUNT = 10;
    private static final int LOOP_COUNT = 1000;

    public static void main(String[] args) throws InterruptedException {
        ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);

        // 多线程并发写入
        for (int i = 0; i < THREAD_COUNT; i++) {
            final int threadId = i;
            executor.submit(() -> {
                for (int j = 0; j < LOOP_COUNT; j++) {
                    map.put(threadId * LOOP_COUNT + j, j);
                }
            });
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);

        // 验证结果
        System.out.println("Map size: " + map.size());
        System.out.println("Expected size: " + (THREAD_COUNT * LOOP_COUNT));
    }
}

2.4 LinkedList适合用什么排序

代码示例:实现归并排序对LinkedList排序

代码语言:java
复制
import java.util.LinkedList;

public class LinkedListMergeSort {
    public static <T extends Comparable<T>> LinkedList<T> sort(LinkedList<T> list) {
        if (list == null || list.size() <= 1) {
            return list;
        }

        // 分割链表
        LinkedList<T> left = new LinkedList<>();
        LinkedList<T> right = new LinkedList<>();
        int mid = list.size() / 2;

        for (int i = 0; i < mid; i++) {
            left.add(list.removeFirst());
        }
        right.addAll(list);

        // 递归排序左右两部分
        left = sort(left);
        right = sort(right);

        // 合并已排序的链表
        return merge(left, right);
    }

    private static <T extends Comparable<T>> LinkedList<T> merge(LinkedList<T> left, LinkedList<T> right) {
        LinkedList<T> result = new LinkedList<>();

        while (!left.isEmpty() && !right.isEmpty()) {
            if (left.peek().compareTo(right.peek()) <= 0) {
                result.add(left.removeFirst());
            } else {
                result.add(right.removeFirst());
            }
        }

        // 添加剩余元素
        result.addAll(left);
        result.addAll(right);

        return result;
    }
}

三、多线程

3.1 创建线程的方式

代码示例:三种创建线程的方式

代码语言:java
复制
// 1. 继承Thread类
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承Thread类创建的线程: " + Thread.currentThread().getName());
    }
}

// 2. 实现Runnable接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("实现Runnable接口创建的线程: " + Thread.currentThread().getName());
    }
}

// 3. 实现Callable接口
import java.util.concurrent.*;

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "实现Callable接口创建的线程: " + Thread.currentThread().getName();
    }
}

public class ThreadCreationDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 方式1: 继承Thread类
        MyThread thread1 = new MyThread();
        thread1.start();

        // 方式2: 实现Runnable接口
        Thread thread2 = new Thread(new MyRunnable());
        thread2.start();

        // 方式3: 实现Callable接口
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new MyCallable());
        System.out.println(future.get());
        executor.shutdown();
    }
}

3.2 线程池相关问题

实操场景:自定义线程池配置

代码语言:java
复制
import java.util.concurrent.*;

public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 创建自定义线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,                   // 核心线程数
                10,                  // 最大线程数
                60,                  // 空闲线程存活时间
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),  // 任务队列
                Executors.defaultThreadFactory(), // 线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );

        // 提交任务
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executor.submit(() -> {
                System.out.println("Task " + taskId + " is running on thread: " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + " completed");
            });
        }

        // 关闭线程池
        executor.shutdown();
    }
}

3.3 线程安全问题

代码示例:使用synchronized和Lock实现线程安全

代码语言:java
复制
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// 1. 使用synchronized关键字
class SynchronizedCounter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

// 2. 使用Lock接口
class LockCounter {
    private int count = 0;
    private final Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

// 3. 使用原子类
import java.util.concurrent.atomic.AtomicInteger;

class AtomicCounter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

3.4 AQS相关问题

代码示例:自定义锁实现

代码语言:java
复制
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

class CustomLock {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0) {
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
    }

    private final Sync sync = new Sync();

    public void lock() {
        sync.acquire(1);
    }

    public void unlock() {
        sync.release(1);
    }

    public boolean tryLock() {
        return sync.tryAcquire(1);
    }
}

四、JVM

4.1 JVM内存区域划分

实操场景:内存溢出测试

代码语言:java
复制
import java.util.ArrayList;
import java.util.List;

public class OutOfMemoryDemo {
    public static void main(String[] args) {
        // 堆内存溢出
        heapOutOfMemory();

        // 栈内存溢出
        // stackOverflow();
    }

    private static void heapOutOfMemory() {
        List<byte[]> list = new ArrayList<>();
        while (true) {
            list.add(new byte[1024 * 1024]); // 每次添加1MB数据
        }
    }

    private static void stackOverflow() {
        stackOverflow(); // 递归调用导致栈溢出
    }
}

4.2 垃圾回收机制

实操场景:GC日志分析

代码语言:bash
复制
# 运行程序时开启GC日志
java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xms256m -Xmx256m OutOfMemoryDemo

# 典型GC日志分析
2025-06-26T10:30:45.123+0800: 0.234: [GC (Allocation Failure) [PSYoungGen: 65536K->256K(76288K)] 65536K->65536K(251392K), 0.0012345 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

# 日志解读:
# 1. GC发生时间: 2025-06-26T10:30:45.123+0800
# 2. GC类型: 新生代GC (Allocation Failure表示内存分配失败触发GC)
# 3. 新生代内存变化: 65536K->256K(76288K)
# 4. 堆内存变化: 65536K->65536K(251392K)
# 5. GC耗时: 0.0012345秒

4.3 类加载机制

代码示例:自定义类加载器

代码语言:java
复制
import java.io.*;

public class CustomClassLoader extends ClassLoader {
    private String classPath;

    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] classData = loadClassData(name);
            if (classData == null) {
                throw new ClassNotFoundException();
            }
            return defineClass(name, classData, 0, classData.length);
        } catch (IOException e) {
            throw new ClassNotFoundException(name, e);
        }
    }

    private byte[] loadClassData(String name) throws IOException {
        String path = classPath + File.separatorChar +
                name.replace('.', File.separatorChar) + ".class";

        try (InputStream is = new FileInputStream(path);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            return bos.toByteArray();
        }
    }

    public static void main(String[] args) throws Exception {
        CustomClassLoader loader = new CustomClassLoader("/path/to/classes");
        Class<?> clazz = loader.loadClass("com.example.MyClass");
        Object obj = clazz.getDeclaredConstructor().newInstance();
        System.out.println(obj.getClass().getClassLoader());
    }
}

4.4 JVM性能调优

实操场景:JVM参数配置

代码语言:bash
复制
# 典型的JVM性能调优参数配置示例
java -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m \
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/java_heapdump.hprof \
-jar myapplication.jar

# 参数说明:
# -Xms512m: 初始堆大小512MB
# -Xmx512m: 最大堆大小512MB
# -Xmn256m: 新生代大小256MB
# -XX:MetaspaceSize=128m: 元空间初始大小128MB
# -XX:MaxMetaspaceSize=256m: 元空间最大大小256MB
# -XX:+UseG1GC: 使用G1垃圾收集器
# -XX:MaxGCPauseMillis=200: 最大GC停顿时间200毫秒
# -XX:+HeapDumpOnOutOfMemoryError: 发生OOM时生成堆转储文件
# -XX:HeapDumpPath=/var/log/java_heapdump.hprof: 堆转储文件路径

五、数据库

5.1 MySQL索引优化

实操场景:索引优化测试

代码语言:sql
复制
-- 创建测试表
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT,
    gender VARCHAR(10),
    email VARCHAR(100),
    create_time DATETIME
);

-- 添加测试数据
INSERT INTO user (name, age, gender, email, create_time)
VALUES ('张三', 25, '男', 'zhangsan@example.com', NOW()),
       ('李四', 30, '男', 'lisi@example.com', NOW()),
       ('王五', 28, '女', 'wangwu@example.com', NOW());

-- 创建复合索引
CREATE INDEX idx_name_age_gender ON user (name, age, gender);

-- 执行计划分析
EXPLAIN SELECT * FROM user WHERE name = '张三' AND age = 25 AND gender = '男';

-- 索引覆盖测试
EXPLAIN SELECT name, age, gender FROM user WHERE name = '张三';

5.2 数据库事务隔离级别

实操场景:演示脏读、不可重复读和幻读

代码语言:sql
复制
-- 设置事务隔离级别为读未提交(会出现脏读)
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 会话1: 开启事务
START TRANSACTION;
UPDATE user SET age = 31 WHERE name = '李四';

-- 会话2: 查询(会读到未提交的数据,出现脏读)
SELECT * FROM user WHERE name = '李四';

-- 会话1: 回滚事务
ROLLBACK;

-- 设置事务隔离级别为可重复读(MySQL默认级别,解决不可重复读,但可能出现幻读)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 会话1: 开启事务并查询
START TRANSACTION;
SELECT * FROM user WHERE age > 25;

-- 会话2: 插入新记录
INSERT INTO user (name, age, gender) VALUES ('赵六', 35, '男');
COMMIT;

-- 会话1: 再次查询(两次查询结果一致,解决不可重复读)
SELECT * FROM user WHERE age > 25;

-- 会话1: 插入相同条件的记录(会出现Duplicate key错误,说明出现幻读)
INSERT INTO user (name, age, gender) VALUES ('赵六', 35, '男');

5.3 MySQL主从复制

实操场景:配置MySQL主从复制

代码语言:bash
复制
# 主库配置 (my.cnf)
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-do-db=test_db

# 从库配置 (my.cnf)
[mysqld]
server-id=2
relay-log=mysql-relay-bin
log-bin=mysql-bin

# 主库操作
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;

# 从库操作
CHANGE MASTER TO
    MASTER_HOST='主库IP',
    MASTER_USER='repl_user',
    MASTER_PASSWORD='password',
    MASTER_LOG_FILE='mysql-bin.xxxxxx',
    MASTER_LOG_POS=xxxxxx;

START SLAVE;
SHOW SLAVE STATUS\G

六、算法

6.1 排序算法

代码示例:实现快速排序

代码语言:java
复制
public class QuickSort {
    public static void sort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }

    private static void quickSort(int[] arr, int left, int right) {
        if (left < right) {
            int pivotIndex = partition(arr, left, right);
            quickSort(arr, left, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, right);
        }
    }

    private static int partition(int[] arr, int left, int right) {
        int pivot = arr[right];
        int i = left - 1;

        for (int j = left; j < right; j++) {
            if (arr[j] <= pivot) {
                i++;
                swap(arr, i, j);
            }
        }

        swap(arr, i + 1, right);
        return i + 1;
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

6.2 查找算法

代码示例:实现二分查找

代码语言:java
复制
public class BinarySearch {
    public static int search(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;

        while (left <= right) {
            int mid = left + (right - left) / 2;

            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        return -1; // 未找到
    }
}

6.3 递归与动态规划

代码示例:斐波那契数列(动态规划优化)

代码语言:java
复制
public class Fibonacci {
    // 递归实现(效率低)
    public static int fibRecursive(int n) {
        if (n <= 1) {
            return n;
        }
        return fibRecursive(n - 1) + fibRecursive(n - 2);
    }

    // 动态规划实现(高效)
    public static int fibDynamic(int n) {
        if (n <= 1) {
            return n;
        }

        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;

        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }

        return dp[n];
    }

    // 优化空间复杂度的动态规划
    public static int fibOptimized(int n) {
        if (n <= 1) {
            return n;
        }

        int a = 0;
        int b = 1;
        int result = 0;

        for (int i = 2; i <= n; i++) {
            result = a + b;
            a = b;
            b = result;
        }

        return result;
    }
}

6.4 链表操作

代码示例:反转链表

代码语言:java
复制
class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

public class ReverseLinkedList {
    // 迭代方法
    public static ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        
        return prev;
    }

    // 递归方法
    public static ListNode reverseListRecursive(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode newHead = reverseListRecursive(head.next);
        head.next.next = head;
        head.next = null;
        
        return newHead;
    }
}

以上代码示例和实操场景展示了Java开发中的核心技术点和面试高频考点。通过实际动手操作这些示例,你可以更深入地理解相关概念和技术,为面试做好充分准备。


百度校招,Java 开发岗,Java 架构师,面试题,历年经典,Java 基础,并发编程,JVM,Spring 框架,微服务,分布式,数据库,算法,数据结构,网络编程


原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java开发岗
  • Java架构师
  • 百度校招Java开发岗历年经典面试题汇总(实操篇)
    • 一、Java基础
      • 1.1 JDK和JRE的区别
      • 1.2 ==和equals的区别
      • 1.3 final的作用
      • 1.4 String相关问题
      • 1.5 抽象类与接口
      • 1.6 Java中IO流
      • 1.7 Files的常用方法
    • 二、容器
      • 2.1 Java容器有哪些
      • 2.2 HashMap相关问题
      • 2.3 ConcurrentHashMap相关问题
      • 2.4 LinkedList适合用什么排序
    • 三、多线程
      • 3.1 创建线程的方式
      • 3.2 线程池相关问题
      • 3.3 线程安全问题
      • 3.4 AQS相关问题
    • 四、JVM
      • 4.1 JVM内存区域划分
      • 4.2 垃圾回收机制
      • 4.3 类加载机制
      • 4.4 JVM性能调优
    • 五、数据库
      • 5.1 MySQL索引优化
      • 5.2 数据库事务隔离级别
      • 5.3 MySQL主从复制
    • 六、算法
      • 6.1 排序算法
      • 6.2 查找算法
      • 6.3 递归与动态规划
      • 6.4 链表操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档