以下是百度校招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的安装与区别
# 检查JDK版本 java -version javac -version # 查看JDK安装路径 which java which javac # 验证JRE是否包含编译器 # 尝试在仅安装JRE的环境中执行javac命令,会提示"command not found" 1.2 ==和equals的区别
代码示例:
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的作用
代码示例:
// 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)
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 抽象类与接口
代码示例:实现多继承特性
// 接口定义 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流
实操场景:文件复制工具实现
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的常用方法
代码示例:文件操作工具类
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容器有哪些
实操场景:容器性能对比测试
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实现
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相关问题
实操场景:多线程环境下的并发操作
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排序
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 创建线程的方式
代码示例:三种创建线程的方式
// 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 线程池相关问题
实操场景:自定义线程池配置
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实现线程安全
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相关问题
代码示例:自定义锁实现
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内存区域划分
实操场景:内存溢出测试
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日志分析
# 运行程序时开启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 类加载机制
代码示例:自定义类加载器
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参数配置
# 典型的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索引优化
实操场景:索引优化测试
-- 创建测试表 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 数据库事务隔离级别
实操场景:演示脏读、不可重复读和幻读
-- 设置事务隔离级别为读未提交(会出现脏读) 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主从复制
# 主库配置 (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 排序算法
代码示例:实现快速排序
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 查找算法
代码示例:实现二分查找
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 递归与动态规划
代码示例:斐波那契数列(动态规划优化)
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 链表操作
代码示例:反转链表
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 框架,MySQL, 分布式,微服务,设计模式
代码获取方式
https://pan.quark.cn/s/14fcf913bae6