Skip to content

Java 集合框架

Java集合框架是Java编程语言中用来表示和操作集合的统一架构。它包含接口、实现类和算法,使得程序员可以高效地处理数据集合。

异常处理

异常体系结构

Java的异常处理机制是程序设计中的重要组成部分,它允许程序优雅地处理运行时错误。

java
// 异常层次结构
// Throwable
//   ├── Error (系统错误,通常不处理)
//   │   ├── OutOfMemoryError
//   │   ├── StackOverflowError
//   │   └── ...
//   └── Exception (程序异常,可以处理)
//       ├── RuntimeException (运行时异常,非检查异常)
//       │   ├── NullPointerException
//       │   ├── ArrayIndexOutOfBoundsException
//       │   ├── IllegalArgumentException
//       │   └── ...
//       └── CheckedException (检查异常,必须处理)
//           ├── IOException
//           ├── SQLException
//           └── ...

// 自定义异常类
class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
    
    public CustomException(String message, Throwable cause) {
        super(message, cause);
    }
}

// 业务异常类
class BusinessException extends RuntimeException {
    private int errorCode;
    
    public BusinessException(int errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }
    
    public int getErrorCode() {
        return errorCode;
    }
}

// 异常处理示例
public class ExceptionHandlingExample {
    public static void main(String[] args) {
        System.out.println("=== 异常处理示例 ===");
        
        // 1. 基本异常处理
        try {
            int result = divide(10, 0);
            System.out.println("结果: " + result);
        } catch (ArithmeticException e) {
            System.out.println("捕获到算术异常: " + e.getMessage());
        }
        
        // 2. 多重异常处理
        try {
            processArray(new int[]{1, 2, 3}, 5);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界异常: " + e.getMessage());
        } catch (IllegalArgumentException e) {
            System.out.println("非法参数异常: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("其他异常: " + e.getMessage());
        } finally {
            System.out.println("finally块总是执行");
        }
        
        // 3. 自定义异常处理
        try {
            validateAge(-5);
        } catch (CustomException e) {
            System.out.println("自定义异常: " + e.getMessage());
        }
        
        // 4. 运行时异常处理
        try {
            String str = null;
            int length = str.length(); // 会抛出NullPointerException
        } catch (NullPointerException e) {
            System.out.println("空指针异常: " + e.getMessage());
        }
        
        // 5. 检查异常处理
        try {
            readFile("nonexistent.txt");
        } catch (java.io.IOException e) {
            System.out.println("IO异常: " + e.getMessage());
        }
        
        // 6. 异常链
        try {
            processBusinessData();
        } catch (BusinessException e) {
            System.out.println("业务异常 [错误码: " + e.getErrorCode() + "]: " + e.getMessage());
            if (e.getCause() != null) {
                System.out.println("原因: " + e.getCause().getMessage());
            }
        }
    }
    
    // 可能抛出算术异常的方法
    public static int divide(int a, int b) {
        return a / b; // 当b为0时抛出ArithmeticException
    }
    
    // 可能抛出多种异常的方法
    public static void processArray(int[] array, int index) {
        if (array == null) {
            throw new IllegalArgumentException("数组不能为null");
        }
        
        if (index < 0) {
            throw new IllegalArgumentException("索引不能为负数");
        }
        
        System.out.println("数组元素: " + array[index]);
    }
    
    // 抛出自定义异常的方法
    public static void validateAge(int age) throws CustomException {
        if (age < 0) {
            throw new CustomException("年龄不能为负数: " + age);
        }
        
        if (age > 150) {
            throw new CustomException("年龄不能超过150: " + age);
        }
        
        System.out.println("有效年龄: " + age);
    }
    
    // 抛出检查异常的方法
    public static void readFile(String filename) throws java.io.IOException {
        java.io.File file = new java.io.File(filename);
        if (!file.exists()) {
            throw new java.io.IOException("文件不存在: " + filename);
        }
        // 实际的文件读取逻辑...
        System.out.println("文件读取成功: " + filename);
    }
    
    // 业务处理方法,演示异常链
    public static void processBusinessData() throws BusinessException {
        try {
            // 模拟数据库操作
            performDatabaseOperation();
        } catch (java.sql.SQLException e) {
            // 将SQLException包装为BusinessException
            throw new BusinessException(1001, "数据库操作失败") {{
                initCause(e);
            }};
        }
    }
    
    // 模拟数据库操作
    public static void performDatabaseOperation() throws java.sql.SQLException {
        // 模拟数据库连接失败
        throw new java.sql.SQLException("数据库连接失败");
    }
}

try-catch-finally 语句

try-catch-finally是Java中处理异常的基本结构,用于捕获和处理异常。

java
// 资源管理类
class ResourceManager {
    private boolean isOpen = false;
    
    public void open() {
        isOpen = true;
        System.out.println("资源已打开");
    }
    
    public void close() {
        if (isOpen) {
            isOpen = false;
            System.out.println("资源已关闭");
        }
    }
    
    public void useResource() throws Exception {
        if (!isOpen) {
            throw new Exception("资源未打开");
        }
        System.out.println("正在使用资源");
        // 模拟使用过程中可能发生的异常
        if (Math.random() > 0.7) {
            throw new Exception("资源使用过程中发生错误");
        }
    }
}

// try-catch-finally示例
public class TryCatchFinallyExample {
    public static void main(String[] args) {
        System.out.println("=== try-catch-finally 示例 ===");
        
        // 1. 基本的try-catch-finally
        basicTryCatchFinally();
        
        // 2. 多重catch块
        multipleCatchBlocks();
        
        // 3. try-with-resources (Java 7+)
        tryWithResources();
        
        // 4. 嵌套的try-catch
        nestedTryCatch();
        
        // 5. 异常在finally中的处理
        exceptionInFinally();
    }
    
    // 基本的try-catch-finally
    public static void basicTryCatchFinally() {
        System.out.println("\n--- 基本try-catch-finally ---");
        ResourceManager resource = new ResourceManager();
        
        try {
            resource.open();
            resource.useResource();
            System.out.println("资源使用成功");
        } catch (Exception e) {
            System.out.println("捕获异常: " + e.getMessage());
        } finally {
            resource.close();
            System.out.println("finally块执行完毕");
        }
    }
    
    // 多重catch块
    public static void multipleCatchBlocks() {
        System.out.println("\n--- 多重catch块 ---");
        int[] numbers = {1, 2, 3};
        
        try {
            // 可能抛出多种异常的代码
            int index = Integer.parseInt("abc"); // NumberFormatException
            System.out.println(numbers[index]);  // ArrayIndexOutOfBoundsException
        } catch (NumberFormatException e) {
            System.out.println("数字格式异常: " + e.getMessage());
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界异常: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("其他异常: " + e.getMessage());
        } finally {
            System.out.println("多重catch示例完成");
        }
    }
    
    // try-with-resources (Java 7+)
    public static void tryWithResources() {
        System.out.println("\n--- try-with-resources ---");
        
        // 使用try-with-resources自动管理资源
        try (java.io.FileWriter writer = new java.io.FileWriter("example.txt");
             java.io.PrintWriter printWriter = new java.io.PrintWriter(writer)) {
            
            printWriter.println("Hello, World!");
            printWriter.println("这是try-with-resources示例");
            
            // 模拟可能的异常
            if (Math.random() > 0.8) {
                throw new Exception("写入过程中发生错误");
            }
            
        } catch (Exception e) {
            System.out.println("捕获异常: " + e.getMessage());
        } finally {
            System.out.println("try-with-resources示例完成");
        }
        
        // 读取文件验证
        try (java.io.BufferedReader reader = java.nio.file.Files.newBufferedReader(
                java.nio.file.Paths.get("example.txt"))) {
            
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("读取到: " + line);
            }
            
        } catch (Exception e) {
            System.out.println("读取文件异常: " + e.getMessage());
        }
    }
    
    // 嵌套的try-catch
    public static void nestedTryCatch() {
        System.out.println("\n--- 嵌套try-catch ---");
        
        try {
            System.out.println("外层try块开始");
            
            try {
                System.out.println("内层try块开始");
                int result = 10 / 0; // 会抛出ArithmeticException
                System.out.println("内层try块结束");
            } catch (ArithmeticException e) {
                System.out.println("内层catch块: " + e.getMessage());
                // 重新抛出异常
                throw new RuntimeException("内层异常重新抛出", e);
            } finally {
                System.out.println("内层finally块执行");
            }
            
            System.out.println("外层try块结束");
        } catch (RuntimeException e) {
            System.out.println("外层catch块: " + e.getMessage());
            if (e.getCause() != null) {
                System.out.println("原因: " + e.getCause().getMessage());
            }
        } finally {
            System.out.println("外层finally块执行");
        }
    }
    
    // 异常在finally中的处理
    public static void exceptionInFinally() {
        System.out.println("\n--- finally中的异常 ---");
        
        try {
            System.out.println("try块执行");
            throw new Exception("try块中的异常");
        } catch (Exception e) {
            System.out.println("catch块: " + e.getMessage());
        } finally {
            System.out.println("finally块执行");
            // finally块中的异常会抑制try块中的异常
            try {
                throw new RuntimeException("finally块中的异常");
            } catch (RuntimeException e) {
                System.out.println("finally中异常被捕获: " + e.getMessage());
            }
        }
    }
}

// 自定义资源类,实现AutoCloseable接口
class CustomResource implements AutoCloseable {
    private String name;
    private boolean closed = false;
    
    public CustomResource(String name) {
        this.name = name;
        System.out.println("创建资源: " + name);
    }
    
    public void doWork() throws Exception {
        if (closed) {
            throw new Exception("资源已关闭,无法工作");
        }
        System.out.println("资源 " + name + " 正在工作");
        
        // 模拟工作过程中可能发生的异常
        if (Math.random() > 0.7) {
            throw new Exception("资源 " + name + " 工作过程中发生错误");
        }
    }
    
    @Override
    public void close() throws Exception {
        if (!closed) {
            closed = true;
            System.out.println("关闭资源: " + name);
            
            // 模拟关闭过程中可能发生的异常
            if (Math.random() > 0.8) {
                throw new Exception("关闭资源 " + name + " 时发生错误");
            }
        }
    }
}

// try-with-resources的高级示例
public class AdvancedTryWithResources {
    public static void main(String[] args) {
        System.out.println("=== 高级try-with-resources示例 ===");
        
        // 1. 多个资源
        multipleResources();
        
        // 2. 自定义资源
        customResource();
        
        // 3. 资源关闭顺序
        resourceClosingOrder();
    }
    
    // 多个资源
    public static void multipleResources() {
        System.out.println("\n--- 多个资源 ---");
        
        try (java.io.FileInputStream fis = new java.io.FileInputStream("input.txt");
             java.io.FileOutputStream fos = new java.io.FileOutputStream("output.txt");
             java.io.BufferedInputStream bis = new java.io.BufferedInputStream(fis);
             java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(fos)) {
            
            // 复制文件
            int data;
            while ((data = bis.read()) != -1) {
                bos.write(data);
            }
            
            System.out.println("文件复制完成");
            
        } catch (java.io.IOException e) {
            System.out.println("IO异常: " + e.getMessage());
        }
    }
    
    // 自定义资源
    public static void customResource() {
        System.out.println("\n--- 自定义资源 ---");
        
        try (CustomResource resource1 = new CustomResource("资源1");
             CustomResource resource2 = new CustomResource("资源2")) {
            
            resource1.doWork();
            resource2.doWork();
            
        } catch (Exception e) {
            System.out.println("异常: " + e.getMessage());
            if (e.getCause() != null) {
                System.out.println("原因: " + e.getCause().getMessage());
            }
        }
    }
    
    // 资源关闭顺序
    public static void resourceClosingOrder() {
        System.out.println("\n--- 资源关闭顺序 ---");
        
        // 资源按照声明的相反顺序关闭
        try (FirstResource first = new FirstResource();
             SecondResource second = new SecondResource();
             ThirdResource third = new ThirdResource()) {
            
            System.out.println("所有资源已创建并使用");
            
        } catch (Exception e) {
            System.out.println("异常: " + e.getMessage());
        }
    }
}

// 演示资源关闭顺序的类
class FirstResource implements AutoCloseable {
    public FirstResource() {
        System.out.println("创建FirstResource");
    }
    
    @Override
    public void close() throws Exception {
        System.out.println("关闭FirstResource");
    }
}

class SecondResource implements AutoCloseable {
    public SecondResource() {
        System.out.println("创建SecondResource");
    }
    
    @Override
    public void close() throws Exception {
        System.out.println("关闭SecondResource");
    }
}

class ThirdResource implements AutoCloseable {
    public ThirdResource() {
        System.out.println("创建ThirdResource");
    }
    
    @Override
    public void close() throws Exception {
        System.out.println("关闭ThirdResource");
    }
}

throws 与 throw 关键字

throws关键字用于声明方法可能抛出的异常,而throw关键字用于主动抛出异常。

java
// 自定义检查异常
class InsufficientFundsException extends Exception {
    private double amount;
    
    public InsufficientFundsException(double amount) {
        super("余额不足,缺少金额: " + amount);
        this.amount = amount;
    }
    
    public double getAmount() {
        return amount;
    }
}

// 自定义运行时异常
class InvalidAccountException extends RuntimeException {
    public InvalidAccountException(String message) {
        super(message);
    }
}

// 银行账户类
class BankAccount {
    private String accountNumber;
    private double balance;
    private String ownerName;
    
    public BankAccount(String accountNumber, String ownerName, double initialBalance) {
        this.accountNumber = accountNumber;
        this.ownerName = ownerName;
        this.balance = initialBalance;
    }
    
    // 存款方法 - 不会抛出检查异常
    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("存款金额必须大于0");
        }
        balance += amount;
        System.out.println("存款成功,当前余额: " + balance);
    }
    
    // 取款方法 - 声明可能抛出检查异常
    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount <= 0) {
            throw new IllegalArgumentException("取款金额必须大于0");
        }
        
        if (amount > balance) {
            // 抛出自定义检查异常
            throw new InsufficientFundsException(amount - balance);
        }
        
        balance -= amount;
        System.out.println("取款成功,当前余额: " + balance);
    }
    
    // 转账方法 - 声明可能抛出多种异常
    public void transfer(BankAccount targetAccount, double amount) 
            throws InsufficientFundsException, InvalidAccountException {
        
        if (targetAccount == null) {
            // 抛出自定义运行时异常
            throw new InvalidAccountException("目标账户不能为空");
        }
        
        if (amount <= 0) {
            throw new IllegalArgumentException("转账金额必须大于0");
        }
        
        // 先检查余额
        if (amount > balance) {
            throw new InsufficientFundsException(amount - balance);
        }
        
        // 执行转账
        this.withdraw(amount);
        targetAccount.deposit(amount);
        System.out.println("转账成功,从 " + this.accountNumber + " 转到 " + targetAccount.accountNumber);
    }
    
    // 验证账户有效性 - 可能抛出运行时异常
    public void validateAccount() throws InvalidAccountException {
        if (accountNumber == null || accountNumber.isEmpty()) {
            throw new InvalidAccountException("账户号码无效");
        }
        
        if (ownerName == null || ownerName.isEmpty()) {
            throw new InvalidAccountException("账户持有人姓名无效");
        }
        
        System.out.println("账户验证通过: " + accountNumber);
    }
    
    // 重置账户 - 演示异常链
    public void resetAccount() throws InsufficientFundsException {
        try {
            // 模拟复杂的重置操作
            performComplexOperation();
        } catch (Exception e) {
            // 将其他异常包装为业务异常
            InsufficientFundsException businessEx = 
                new InsufficientFundsException(0);
            businessEx.initCause(e);
            throw businessEx;
        }
    }
    
    // 模拟复杂操作
    private void performComplexOperation() throws Exception {
        // 模拟操作失败
        if (Math.random() > 0.7) {
            throw new Exception("复杂操作执行失败");
        }
        System.out.println("复杂操作执行成功");
    }
    
    // getter方法
    public String getAccountNumber() {
        return accountNumber;
    }
    
    public double getBalance() {
        return balance;
    }
    
    public String getOwnerName() {
        return ownerName;
    }
}

// throws与throw关键字示例
public class ThrowsThrowExample {
    public static void main(String[] args) {
        System.out.println("=== throws与throw关键字示例 ===");
        
        // 1. 基本的throws使用
        basicThrowsUsage();
        
        // 2. throw关键字使用
        throwKeywordUsage();
        
        // 3. 异常链演示
        exceptionChaining();
        
        // 4. 多重异常声明
        multipleExceptionDeclaration();
        
        // 5. 异常处理最佳实践
        exceptionBestPractices();
    }
    
    // 基本的throws使用
    public static void basicThrowsUsage() {
        System.out.println("\n--- 基本throws使用 ---");
        
        BankAccount account = new BankAccount("123456", "张三", 1000.0);
        
        try {
            // 调用声明throws的方法
            account.withdraw(500.0);
            System.out.println("取款500成功");
        } catch (InsufficientFundsException e) {
            System.out.println("取款失败: " + e.getMessage());
            System.out.println("缺少金额: " + e.getAmount());
        }
        
        try {
            // 尝试取款超过余额
            account.withdraw(1500.0);
        } catch (InsufficientFundsException e) {
            System.out.println("取款失败: " + e.getMessage());
            System.out.println("缺少金额: " + e.getAmount());
        }
    }
    
    // throw关键字使用
    public static void throwKeywordUsage() {
        System.out.println("\n--- throw关键字使用 ---");
        
        BankAccount account = new BankAccount("789012", "李四", 2000.0);
        
        try {
            // 正常存款
            account.deposit(500.0);
            
            // 尝试存入负数(会抛出运行时异常)
            account.deposit(-100.0);
        } catch (IllegalArgumentException e) {
            System.out.println("存款异常: " + e.getMessage());
        }
        
        try {
            // 验证账户
            account.validateAccount();
            
            // 创建无效账户并验证(会抛出运行时异常)
            BankAccount invalidAccount = new BankAccount("", "", 0);
            invalidAccount.validateAccount();
        } catch (InvalidAccountException e) {
            System.out.println("账户验证异常: " + e.getMessage());
        }
    }
    
    // 异常链演示
    public static void exceptionChaining() {
        System.out.println("\n--- 异常链演示 ---");
        
        BankAccount account = new BankAccount("345678", "王五", 1500.0);
        
        try {
            // 调用会引发异常链的方法
            account.resetAccount();
        } catch (InsufficientFundsException e) {
            System.out.println("业务异常: " + e.getMessage());
            if (e.getCause() != null) {
                System.out.println("根本原因: " + e.getCause().getMessage());
            }
        }
    }
    
    // 多重异常声明
    public static void multipleExceptionDeclaration() {
        System.out.println("\n--- 多重异常声明 ---");
        
        BankAccount sourceAccount = new BankAccount("111111", "赵六", 3000.0);
        BankAccount targetAccount = new BankAccount("222222", "钱七", 500.0);
        
        try {
            // 正常转账
            sourceAccount.transfer(targetAccount, 1000.0);
            System.out.println("转账成功");
        } catch (InsufficientFundsException e) {
            System.out.println("余额不足: " + e.getMessage());
        } catch (InvalidAccountException e) {
            System.out.println("账户无效: " + e.getMessage());
        }
        
        try {
            // 转账到null账户
            sourceAccount.transfer(null, 500.0);
        } catch (InsufficientFundsException | InvalidAccountException e) {
            // Java 7+ 多重catch
            System.out.println("转账异常: " + e.getMessage());
        }
        
        try {
            // 余额不足转账
            sourceAccount.transfer(targetAccount, 5000.0);
        } catch (InsufficientFundsException e) {
            System.out.println("转账失败 - " + e.getMessage());
        } catch (InvalidAccountException e) {
            System.out.println("转账失败 - " + e.getMessage());
        }
    }
    
    // 异常处理最佳实践
    public static void exceptionBestPractices() {
        System.out.println("\n--- 异常处理最佳实践 ---");
        
        BankAccount account = new BankAccount("999999", "孙八", 100.0);
        
        // 1. 具体异常优于通用异常
        try {
            account.deposit(-50.0);
        } catch (IllegalArgumentException e) {
            System.out.println("具体异常处理: " + e.getMessage());
        }
        
        // 2. 早期检查,快速失败
        try {
            if (account.getBalance() < 200.0) {
                throw new InsufficientFundsException(200.0 - account.getBalance());
            }
            System.out.println("余额充足,可以进行操作");
        } catch (InsufficientFundsException e) {
            System.out.println("预检查失败: " + e.getMessage());
        }
        
        // 3. 异常信息要详细
        try {
            account.transfer(null, 100.0);
        } catch (InvalidAccountException e) {
            System.out.println("详细异常信息: " + e.getMessage() + 
                             " [操作类型: 转账, 操作账户: " + account.getAccountNumber() + "]");
        } catch (InsufficientFundsException e) {
            System.out.println("详细异常信息: " + e.getMessage() + 
                             " [操作类型: 转账, 操作账户: " + account.getAccountNumber() + 
                             ", 缺少金额: " + e.getAmount() + "]");
        }
    }
}

// 异常处理工具类
class ExceptionUtils {
    // 包装检查异常为运行时异常
    public static <T> T unchecked(java.util.concurrent.Callable<T> callable) {
        try {
            return callable.call();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    // 包装Runnable中的检查异常
    public static void unchecked(java.lang.Runnable runnable) {
        try {
            runnable.run();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    // 获取异常的根原因
    public static Throwable getRootCause(Throwable throwable) {
        Throwable cause = throwable;
        while (cause.getCause() != null) {
            cause = cause.getCause();
        }
        return cause;
    }
    
    // 打印完整的异常链
    public static void printExceptionChain(Throwable throwable) {
        System.out.println("异常链:");
        Throwable cause = throwable;
        int level = 0;
        while (cause != null) {
            for (int i = 0; i < level; i++) {
                System.out.print("  ");
            }
            System.out.println(cause.getClass().getSimpleName() + ": " + cause.getMessage());
            cause = cause.getCause();
            level++;
        }
    }
}

// 异常工具类使用示例
public class ExceptionUtilsExample {
    public static void main(String[] args) {
        System.out.println("=== 异常工具类使用示例 ===");
        
        // 1. 包装检查异常
        try {
            String content = ExceptionUtils.unchecked(() -> {
                return java.nio.file.Files.readString(
                    java.nio.file.Paths.get("nonexistent.txt"));
            });
            System.out.println("文件内容: " + content);
        } catch (RuntimeException e) {
            System.out.println("包装的异常: " + e.getMessage());
            ExceptionUtils.printExceptionChain(e);
        }
        
        // 2. 获取根原因
        try {
            BankAccount account = new BankAccount("123", "测试", 100);
            account.resetAccount();
        } catch (InsufficientFundsException e) {
            Throwable rootCause = ExceptionUtils.getRootCause(e);
            System.out.println("根原因: " + rootCause.getClass().getSimpleName() + 
                             ": " + rootCause.getMessage());
        }
    }
}

集合框架进阶

HashMap 与 HashSet 原理

HashMap和HashSet是Java集合框架中最重要的类之一,理解它们的内部实现原理对于高效使用它们至关重要。

java
import java.util.*;

// 简化版HashMap实现,用于演示原理
class SimpleHashMap<K, V> {
    // 默认初始容量
    private static final int DEFAULT_CAPACITY = 16;
    // 负载因子
    private static final float LOAD_FACTOR = 0.75f;
    
    // Entry节点类
    static class Entry<K, V> {
        K key;
        V value;
        Entry<K, V> next;
        int hash;
        
        Entry(int hash, K key, V value, Entry<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }
    
    // 存储桶数组
    private Entry<K, V>[] table;
    // 实际存储的键值对数量
    private int size;
    // 阈值,当size超过此值时需要扩容
    private int threshold;
    
    // 构造方法
    @SuppressWarnings("unchecked")
    public SimpleHashMap() {
        table = new Entry[DEFAULT_CAPACITY];
        threshold = (int) (DEFAULT_CAPACITY * LOAD_FACTOR);
    }
    
    // 简单的哈希函数
    private int hash(Object key) {
        if (key == null) {
            return 0;
        }
        int h = key.hashCode();
        // 扰动函数,减少哈希冲突
        return h ^ (h >>> 16);
    }
    
    // 计算数组索引
    private int indexFor(int hash, int length) {
        return hash & (length - 1);
    }
    
    // 获取值
    public V get(Object key) {
        int hash = hash(key);
        int index = indexFor(hash, table.length);
        
        for (Entry<K, V> e = table[index]; e != null; e = e.next) {
            if (e.hash == hash && (e.key == key || (key != null && key.equals(e.key)))) {
                return e.value;
            }
        }
        return null;
    }
    
    // 存储键值对
    public V put(K key, V value) {
        // 检查是否需要扩容
        if (size >= threshold) {
            resize();
        }
        
        int hash = hash(key);
        int index = indexFor(hash, table.length);
        
        // 遍历链表查找是否已存在该key
        for (Entry<K, V> e = table[index]; e != null; e = e.next) {
            if (e.hash == hash && (e.key == key || (key != null && key.equals(e.key)))) {
                V oldValue = e.value;
                e.value = value;
                return oldValue;
            }
        }
        
        // 不存在则添加新节点
        addEntry(hash, key, value, index);
        return null;
    }
    
    // 添加新节点
    private void addEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K, V> entry = table[bucketIndex];
        table[bucketIndex] = new Entry<>(hash, key, value, entry);
        size++;
    }
    
    // 扩容
    @SuppressWarnings("unchecked")
    private void resize() {
        Entry<K, V>[] oldTable = table;
        int oldCapacity = oldTable.length;
        int newCapacity = oldCapacity << 1; // 扩大一倍
        
        // 创建新数组
        Entry<K, V>[] newTable = new Entry[newCapacity];
        
        // 重新哈希所有元素
        transfer(newTable);
        
        table = newTable;
        threshold = (int) (newCapacity * LOAD_FACTOR);
    }
    
    // 转移元素到新数组
    private void transfer(Entry<K, V>[] newTable) {
        Entry<K, V>[] src = table;
        int newCapacity = newTable.length;
        
        for (int j = 0; j < src.length; j++) {
            Entry<K, V> e = src[j];
            if (e != null) {
                src[j] = null;
                do {
                    Entry<K, V> next = e.next;
                    int i = indexFor(e.hash, newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }
    
    // 获取大小
    public int size() {
        return size;
    }
    
    // 检查是否为空
    public boolean isEmpty() {
        return size == 0;
    }
    
    // 移除键值对
    public V remove(Object key) {
        int hash = hash(key);
        int index = indexFor(hash, table.length);
        
        Entry<K, V> prev = table[index];
        Entry<K, V> e = prev;
        
        while (e != null) {
            Entry<K, V> next = e.next;
            if (e.hash == hash && (e.key == key || (key != null && key.equals(e.key)))) {
                size--;
                if (prev == e) {
                    table[index] = next;
                } else {
                    prev.next = next;
                }
                return e.value;
            }
            prev = e;
            e = next;
        }
        return null;
    }
}

// HashMap原理演示
public class HashMapPrinciple {
    public static void main(String[] args) {
        System.out.println("=== HashMap原理演示 ===");
        
        // 1. 基本操作演示
        basicOperations();
        
        // 2. 哈希冲突演示
        hashCollision();
        
        // 3. 扩容演示
        resizeDemo();
        
        // 4. 性能比较
        performanceComparison();
        
        // 5. 线程安全问题
        threadSafetyIssue();
    }
    
    // 基本操作演示
    public static void basicOperations() {
        System.out.println("\n--- 基本操作演示 ---");
        
        // 使用Java内置HashMap
        Map<String, Integer> map = new HashMap<>();
        
        // 添加元素
        map.put("apple", 10);
        map.put("banana", 20);
        map.put("orange", 30);
        
        System.out.println("添加元素后: " + map);
        System.out.println("大小: " + map.size());
        
        // 获取元素
        System.out.println("apple的数量: " + map.get("apple"));
        System.out.println("grape的数量: " + map.get("grape")); // 返回null
        
        // 检查键是否存在
        System.out.println("是否包含apple键: " + map.containsKey("apple"));
        System.out.println("是否包含grape键: " + map.containsKey("grape"));
        
        // 检查值是否存在
        System.out.println("是否包含值20: " + map.containsValue(20));
        
        // 更新元素
        map.put("apple", 15);
        System.out.println("更新apple后: " + map);
        
        // 移除元素
        Integer removedValue = map.remove("banana");
        System.out.println("移除banana: " + removedValue);
        System.out.println("移除后: " + map);
        
        // 遍历HashMap
        System.out.println("遍历键值对:");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
    
    // 哈希冲突演示
    public static void hashCollision() {
        System.out.println("\n--- 哈希冲突演示 ---");
        
        // 创建会哈希冲突的键
        class BadHashKey {
            private String value;
            
            public BadHashKey(String value) {
                this.value = value;
            }
            
            @Override
            public int hashCode() {
                // 故意返回相同的哈希码,制造哈希冲突
                return 1;
            }
            
            @Override
            public boolean equals(Object obj) {
                if (this == obj) return true;
                if (obj == null || getClass() != obj.getClass()) return false;
                BadHashKey that = (BadHashKey) obj;
                return Objects.equals(value, that.value);
            }
            
            @Override
            public String toString() {
                return "BadHashKey{" + value + "}";
            }
        }
        
        Map<BadHashKey, String> map = new HashMap<>();
        
        // 添加多个键值对,它们会有相同的哈希码
        for (int i = 0; i < 5; i++) {
            map.put(new BadHashKey("key" + i), "value" + i);
        }
        
        System.out.println("哈希冲突的Map: " + map);
        System.out.println("大小: " + map.size());
        
        // 查看性能影响
        long startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            map.get(new BadHashKey("key" + (i % 5)));
        }
        long endTime = System.nanoTime();
        System.out.println("1000次查找耗时: " + (endTime - startTime) / 1000000.0 + " ms");
    }
    
    // 扩容演示
    public static void resizeDemo() {
        System.out.println("\n--- 扩容演示 ---");
        
        // 创建初始容量为4的HashMap
        Map<Integer, String> map = new HashMap<>(4);
        
        System.out.println("初始容量: " + getCapacity(map));
        
        // 添加元素观察扩容
        for (int i = 0; i < 15; i++) {
            map.put(i, "value" + i);
            if (i == 3 || i == 6 || i == 12) {
                System.out.println("添加" + (i + 1) + "个元素后,容量: " + getCapacity(map));
            }
        }
        
        System.out.println("最终大小: " + map.size());
        System.out.println("最终容量: " + getCapacity(map));
    }
    
    // 获取HashMap的容量(通过反射)
    private static int getCapacity(Map<?, ?> map) {
        try {
            Field tableField = HashMap.class.getDeclaredField("table");
            tableField.setAccessible(true);
            Object[] table = (Object[]) tableField.get(map);
            return table == null ? 0 : table.length;
        } catch (Exception e) {
            return -1;
        }
    }
    
    // 性能比较
    public static void performanceComparison() {
        System.out.println("\n--- 性能比较 ---");
        
        int testSize = 100000;
        
        // 测试HashMap性能
        Map<Integer, String> hashMap = new HashMap<>();
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < testSize; i++) {
            hashMap.put(i, "value" + i);
        }
        
        long putTime = System.currentTimeMillis() - startTime;
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < testSize; i++) {
            hashMap.get(i);
        }
        
        long getTime = System.currentTimeMillis() - startTime;
        
        System.out.println("HashMap性能测试 (" + testSize + "元素):");
        System.out.println("  插入耗时: " + putTime + " ms");
        System.out.println("  查找耗时: " + getTime + " ms");
        
        // 测试TreeMap性能(作为对比)
        Map<Integer, String> treeMap = new TreeMap<>();
        startTime = System.currentTimeMillis();
        
        for (int i = 0; i < testSize; i++) {
            treeMap.put(i, "value" + i);
        }
        
        long treePutTime = System.currentTimeMillis() - startTime;
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < testSize; i++) {
            treeMap.get(i);
        }
        
        long treeGetTime = System.currentTimeMillis() - startTime;
        
        System.out.println("TreeMap性能测试 (" + testSize + "元素):");
        System.out.println("  插入耗时: " + treePutTime + " ms");
        System.out.println("  查找耗时: " + treeGetTime + " ms");
    }
    
    // 线程安全问题演示
    public static void threadSafetyIssue() {
        System.out.println("\n--- 线程安全问题演示 ---");
        
        final Map<String, Integer> map = new HashMap<>();
        
        // 创建多个线程同时操作HashMap
        Thread[] threads = new Thread[10];
        
        for (int i = 0; i < threads.length; i++) {
            final int threadNum = i;
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    map.put("key" + threadNum + "_" + j, j);
                    map.get("key" + threadNum + "_" + (j - 1));
                }
            });
        }
        
        long startTime = System.currentTimeMillis();
        
        // 启动所有线程
        for (Thread thread : threads) {
            thread.start();
        }
        
        // 等待所有线程完成
        try {
            for (Thread thread : threads) {
                thread.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        long endTime = System.currentTimeMillis();
        
        System.out.println("多线程操作HashMap:");
        System.out.println("  期望大小: " + (10 * 1000));
        System.out.println("  实际大小: " + map.size());
        System.out.println("  耗时: " + (endTime - startTime) + " ms");
        System.out.println("  注意: 可能出现ConcurrentModificationException");
    }
}

// HashSet原理演示
class HashSetPrinciple {
    public static void main(String[] args) {
        System.out.println("=== HashSet原理演示 ===");
        
        // 1. HashSet基本操作
        basicOperations();
        
        // 2. HashSet与HashMap的关系
        relationshipWithHashMap();
        
        // 3. 自定义对象的HashSet使用
        customObjectHashSet();
        
        // 4. LinkedHashSet演示
        linkedHashSetDemo();
    }
    
    // HashSet基本操作
    public static void basicOperations() {
        System.out.println("\n--- HashSet基本操作 ---");
        
        Set<String> set = new HashSet<>();
        
        // 添加元素
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("apple"); // 重复元素不会被添加
        
        System.out.println("添加元素后: " + set);
        System.out.println("大小: " + set.size());
        
        // 检查元素是否存在
        System.out.println("是否包含apple: " + set.contains("apple"));
        System.out.println("是否包含grape: " + set.contains("grape"));
        
        // 移除元素
        boolean removed = set.remove("banana");
        System.out.println("移除banana: " + removed);
        System.out.println("移除后: " + set);
        
        // 遍历HashSet
        System.out.println("遍历元素:");
        for (String fruit : set) {
            System.out.println("  " + fruit);
        }
    }
    
    // HashSet与HashMap的关系
    public static void relationshipWithHashMap() {
        System.out.println("\n--- HashSet与HashMap的关系 ---");
        
        // HashSet内部使用HashMap实现
        Set<String> hashSet = new HashSet<>();
        
        // 添加元素到HashSet
        hashSet.add("element1");
        hashSet.add("element2");
        hashSet.add("element3");
        
        System.out.println("HashSet内容: " + hashSet);
        
        // 通过反射查看HashSet的内部实现
        try {
            Field mapField = HashSet.class.getDeclaredField("map");
            mapField.setAccessible(true);
            Map<?, ?> internalMap = (Map<?, ?>) mapField.get(hashSet);
            
            System.out.println("HashSet内部使用的Map类型: " + internalMap.getClass().getSimpleName());
            System.out.println("内部Map大小: " + internalMap.size());
            
            // 查看内部Map的内容
            System.out.println("内部Map键集: " + internalMap.keySet());
        } catch (Exception e) {
            System.out.println("无法访问内部Map: " + e.getMessage());
        }
    }
    
    // 自定义对象的HashSet使用
    public static void customObjectHashSet() {
        System.out.println("\n--- 自定义对象的HashSet使用 ---");
        
        // 不重写hashCode和equals的类
        class PersonWithoutOverride {
            private String name;
            private int age;
            
            public PersonWithoutOverride(String name, int age) {
                this.name = name;
                this.age = age;
            }
            
            @Override
            public String toString() {
                return "Person{name='" + name + "', age=" + age + "}";
            }
        }
        
        // 重写hashCode和equals的类
        class PersonWithOverride {
            private String name;
            private int age;
            
            public PersonWithOverride(String name, int age) {
                this.name = name;
                this.age = age;
            }
            
            @Override
            public boolean equals(Object obj) {
                if (this == obj) return true;
                if (obj == null || getClass() != obj.getClass()) return false;
                PersonWithOverride that = (PersonWithOverride) obj;
                return age == that.age && Objects.equals(name, that.name);
            }
            
            @Override
            public int hashCode() {
                return Objects.hash(name, age);
            }
            
            @Override
            public String toString() {
                return "Person{name='" + name + "', age=" + age + "}";
            }
        }
        
        // 测试不重写hashCode和equals的情况
        Set<PersonWithoutOverride> set1 = new HashSet<>();
        PersonWithoutOverride p1 = new PersonWithoutOverride("张三", 25);
        PersonWithoutOverride p2 = new PersonWithoutOverride("张三", 25);
        
        set1.add(p1);
        set1.add(p2); // 即使内容相同,也会被当作不同对象
        
        System.out.println("不重写hashCode和equals的HashSet:");
        System.out.println("  大小: " + set1.size()); // 输出2
        System.out.println("  内容: " + set1);
        
        // 测试重写hashCode和equals的情况
        Set<PersonWithOverride> set2 = new HashSet<>();
        PersonWithOverride p3 = new PersonWithOverride("李四", 30);
        PersonWithOverride p4 = new PersonWithOverride("李四", 30);
        
        set2.add(p3);
        set2.add(p4); // 内容相同,会被当作同一对象
        
        System.out.println("重写hashCode和equals的HashSet:");
        System.out.println("  大小: " + set2.size()); // 输出1
        System.out.println("  内容: " + set2);
    }
    
    // LinkedHashSet演示
    public static void linkedHashSetDemo() {
        System.out.println("\n--- LinkedHashSet演示 ---");
        
        // HashSet不保证顺序
        Set<String> hashSet = new HashSet<>();
        hashSet.add("C");
        hashSet.add("A");
        hashSet.add("B");
        hashSet.add("D");
        
        System.out.println("HashSet顺序: " + hashSet);
        
        // LinkedHashSet保持插入顺序
        Set<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("C");
        linkedHashSet.add("A");
        linkedHashSet.add("B");
        linkedHashSet.add("D");
        
        System.out.println("LinkedHashSet顺序: " + linkedHashSet);
        
        // TreeSet保持排序顺序
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("C");
        treeSet.add("A");
        treeSet.add("B");
        treeSet.add("D");
        
        System.out.println("TreeSet顺序: " + treeSet);
    }
}

通过本章节的学习,您已经掌握了Java异常处理机制的核心概念,包括异常体系结构、try-catch-finally语句的使用、throws与throw关键字的应用,以及HashMap和HashSet的实现原理。这些知识对于编写健壮、高效的Java程序至关重要。