JavaSE高级(三)

JAVA常用API

Math类

Java中的Math类位于java.lang包中,提供了许多用于执行基本数学运算的静态方法,如指数、对数、平方根和三角函数等。

主要特点

  1. 静态方法:所有方法都是静态的,可以直接通过类名调用
  2. 不可继承Math类是final类,不能被继承
  3. 不可实例化 :构造函数是私有的,不能创建Math类的对象

常用方法

基本运算
  • Math.abs(a) - 返回绝对值
  • Math.max(a, b) - 返回两个值中的较大值
  • Math.min(a, b) - 返回两个值中的较小值
指数和对数
  • Math.exp(a) - 返回e的a次幂
  • Math.log(a) - 返回自然对数(底为e)
  • Math.log10(a) - 返回底为10的对数
  • Math.pow(a, b) - 返回a的b次幂
  • Math.sqrt(a) - 返回平方根
三角函数
  • Math.sin(a) - 正弦函数
  • Math.cos(a) - 余弦函数
  • Math.tan(a) - 正切函数
  • Math.asin(a) - 反正弦函数
  • Math.acos(a) - 反余弦函数
  • Math.atan(a) - 反正切函数
舍入运算
  • Math.ceil(a) - 向上取整
  • Math.floor(a) - 向下取整
  • Math.round(a) - 四舍五入
  • Math.rint(a) - 返回最接近的整数(double类型)
随机数
  • Math.random() - 返回[0.0, 1.0)之间的随机double值
常量
  • Math.PI - π的近似值
  • Math.E - e的近似值(自然对数的底)
示例代码
typescript 复制代码
public class MathExample {
    public static void main(String[] args) {
        // 基本运算
        System.out.println("绝对值: " + Math.abs(-5));  // 5
        System.out.println("最大值: " + Math.max(10, 20));  // 20
        
        // 指数和对数
        System.out.println("2的3次方: " + Math.pow(2, 3));  // 8.0
        System.out.println("平方根: " + Math.sqrt(16));  // 4.0
        
        // 三角函数
        System.out.println("sin(π/2): " + Math.sin(Math.PI/2));  // 1.0
        
        // 舍入运算
        System.out.println("向上取整: " + Math.ceil(3.2));  // 4.0
        System.out.println("四舍五入: " + Math.round(3.6));  // 4
        
        // 随机数
        System.out.println("随机数: " + Math.random());
        
        // 常量
        System.out.println("π的值: " + Math.PI);
    }
}
注意事项
  1. Math类的方法都是静态的,不需要创建对象即可使用
  2. 对于大数运算,可以考虑使用BigIntegerBigDecimal
  3. 随机数生成更复杂的需求可以使用java.util.Random

Java8之后,还新增了,Math类的增强方法,如精确加法Math.addExact()等,可以在运算溢出时抛出异常

System类

System类是Java核心类库中的一个重要类,位于java.lang包中,提供了与系统相关的实用方法和字段。它不能被实例化,所有方法和字段都是静态的。

主要功能

标准I/O流
  • System.out - 标准输出流(通常是控制台)
  • System.in - 标准输入流
  • System.err - 标准错误输出流
系统属性和环境变量
  • System.getProperties() - 获取所有系统属性
  • System.getProperty(String key) - 获取指定系统属性
  • System.getenv() - 获取所有环境变量
  • System.getenv(String name) - 获取指定环境变量
系统操作
  • System.currentTimeMillis() - 获取当前时间(毫秒)
  • System.nanoTime() - 获取高精度时间(纳秒)
  • System.exit(int status) - 终止JVM
  • System.gc() - 建议JVM运行垃圾回收
  • System.arraycopy() - 数组复制
示例代码
arduino 复制代码
// 输出到控制台
System.out.println("Hello World");
// 读取用户输入
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// 输出错误信息
System.err.println("Error occurred");


// 获取所有系统属性
Properties props = System.getProperties();
props.list(System.out);
// 获取特定属性
String osName = System.getProperty("os.name");
String javaVersion = System.getProperty("java.version");
String userHome = System.getProperty("user.home");

System.out.println("OS: " + osName);
System.out.println("Java Version: " + javaVersion);
System.out.println("User Home: " + userHome);


// 获取所有环境变量
Map<String, String> env = System.getenv();
env.forEach((k, v) -> System.out.println(k + "=" + v));
// 获取特定环境变量
String path = System.getenv("PATH");
System.out.println("PATH: " + path);


// 获取当前时间(毫秒)
long start = System.currentTimeMillis();
// 执行一些操作
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("耗时: " + (end - start) + "ms");
// 高精度时间(纳秒)
long nanoStart = System.nanoTime();
// 执行一些操作
long nanoEnd = System.nanoTime();
System.out.println("耗时: " + (nanoEnd - nanoStart) + "ns");

// 数组复制
int[] src = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(src, 0, dest, 0, src.length);
System.out.println(Arrays.toString(dest));

// 垃圾回收(只是建议)
System.gc();
// 退出程序
System.exit(0);  // 0表示正常退出
常用系统属性
属性名 描述
java.version Java运行时环境版本
java.home Java安装目录
os.name 操作系统名称
os.name 操作系统版本
user.name 用户账户名称
user.home 用户主目录
user.dir
注意事项
  1. System.exit()会立即终止JVM,应谨慎使用
  2. System.gc()只是建议JVM进行垃圾回收,不保证立即执行
  3. 系统属性和环境变量在不同操作系统上可能不同
  4. nanoTime()适合测量时间间隔,不适合获取当前时间

System类提供了许多与系统交互的基础功能,是Java编程中常用的工具类之一。

Runtime类

Runtime类是Java中表示运行时环境的类,允许应用程序与其运行的环境进行交互。每个Java应用程序都有一个Runtime实例,可以通过Runtime.getRuntime()方法获取。

主要功能

  1. 执行系统命令 - 可以运行外部程序
  2. 内存管理 - 查看和调整JVM内存使用情况
  3. 关闭钩子 - 添加JVM关闭时执行的代码
  4. 垃圾回收 - 控制垃圾收集器
  5. 终止JVM - 停止Java虚拟机运行

获取Runtime实例

由于Runtime类的构造函数是私有的,不能直接实例化,必须通过静态方法获取:

ini 复制代码
Runtime runtime = Runtime.getRuntime();

常用方法

1. 执行外部程序
arduino 复制代码
// 执行简单命令
Process process = runtime.exec("notepad.exe");

// 执行带参数的命令
Process process = runtime.exec(new String[]{"cmd", "/c", "dir"});

// 获取命令输出
BufferedReader reader = new BufferedReader(
    new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

// 等待命令执行完成
int exitCode = process.waitFor();
System.out.println("Exit code: " + exitCode);
2. 内存管理
csharp 复制代码
// 获取JVM最大内存量(字节)
long maxMemory = runtime.maxMemory();
System.out.println("Max memory: " + maxMemory / (1024 * 1024) + "MB");

// 获取JVM已分配内存量
long totalMemory = runtime.totalMemory();
System.out.println("Total memory: " + totalMemory / (1024 * 1024) + "MB");

// 获取JVM空闲内存量
long freeMemory = runtime.freeMemory();
System.out.println("Free memory: " + freeMemory / (1024 * 1024) + "MB");

// 计算已使用内存
long usedMemory = totalMemory - freeMemory;
System.out.println("Used memory: " + usedMemory / (1024 * 1024) + "MB");
3. 垃圾回收
scss 复制代码
// 建议JVM进行垃圾回收
runtime.gc();

// 等同于System.gc()
System.gc();
4. 关闭钩子
csharp 复制代码
// 添加JVM关闭时执行的代码
runtime.addShutdownHook(new Thread() {
    public void run() {
        System.out.println("JVM正在关闭...");
        // 执行清理工作
    }
});
5. 终止JVM
arduino 复制代码
// 终止JVM运行,参数为状态码(0表示正常退出)
runtime.exit(0);

// 等同于System.exit(0)
System.exit(0);
完整示例
arduino 复制代码
Runtime runtime = Runtime.getRuntime();

// 内存信息
System.out.println("=== 内存信息 ===");
System.out.printf("Max memory: %.2f MB\n", runtime.maxMemory() / 1024.0 / 1024);
System.out.printf("Total memory: %.2f MB\n", runtime.totalMemory() / 1024.0 / 1024);
System.out.printf("Free memory: %.2f MB\n", runtime.freeMemory() / 1024.0 / 1024);

// 添加关闭钩子
runtime.addShutdownHook(new Thread(() -> {
    System.out.println("\n执行清理工作...");
}));

// 执行外部程序
try {
    System.out.println("\n=== 执行记事本 ===");
    Process process = runtime.exec("notepad.exe");

    // 等待5秒后关闭记事本
    Thread.sleep(5000);
    process.destroy();

    System.out.println("\n=== 执行dir命令 ===");
    Process dirProcess = runtime.exec(new String[]{"cmd", "/c", "dir"});

    // 读取命令输出
    BufferedReader reader = new BufferedReader(new InputStreamReader(dirProcess.getInputStream(), "GBK"));
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

    int exitCode = dirProcess.waitFor();
    System.out.println("Exit code: " + exitCode);

} catch (IOException | InterruptedException e) {
    e.printStackTrace();
}

// 建议垃圾回收
runtime.gc();
注意事项
  1. 安全性exec()方法可能带来安全风险,需谨慎使用
  2. 平台依赖性:执行的命令在不同操作系统上可能不同
  3. 资源释放Process对象使用后应调用destroy()释放资源
  4. 阻塞风险exec()可能阻塞,应考虑使用线程处理
  5. 内存限制maxMemory()返回的是JVM最大可用内存,不是系统总内存

Runtime类提供了与系统运行时环境交互的强大功能,特别是在需要执行外部命令或管理内存时非常有用。

Object类和Objects

Object

Object类是Java中所有类的超类(根类),位于java.lang包中。每个类都直接或间接继承自Object类,即使没有显式声明extends Object

主要方法
1. toStirng()

返回对象的字符串表示形式,默认返回"类名@哈希码"。

typescript 复制代码
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

重写示例:

typescript 复制代码
@Override
public String toString() {
    return "Person{name='" + name + "', age=" + age + "}";
}
2. equals(Object obj)

比较两个对象是否"相等",默认实现是比较引用是否相同(==)。

typescript 复制代码
public boolean equals(Object obj) {
    return (this == obj);
}

重写示例:

ini 复制代码
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}
3. hashCode()

返回对象的哈希码值,用于哈希表(HashMap)中

csharp 复制代码
public native int hashCode();

重写规则:

  • 如果两个对象的equals()返回true,它们的hashCode()必须相同
  • 但hashCode()相同的对象,equals()不一定返回true

重写示例:

csharp 复制代码
@Override
public int hashCode() {
    return Objects.hash(name, age);
}
4. getClass()

返回对象运行时类(Class对象)

arduino 复制代码
public final native Class<?> getClass();

使用示例:

ini 复制代码
Class<?> clazz = obj.getClass();
System.out.println("Class name: " + clazz.getName());
5. clone()

创建并返回对象的一个副本(浅拷贝)

java 复制代码
protected native Object clone() throws CloneNotSupportedException;

使用要求:

  • 类必须实现Cloneable接口
  • 通常需要重写为public方法

示例:

java 复制代码
@Override
public Object clone() throws CloneNotSupportedException {
    return super.clone();
}
6. finalize()

垃圾回收器在回收对象前调用的方法(已弃用,JDK9+)

csharp 复制代码
protected void finalize() throws Throwable { }
7. wait(),notify(),notifyAll()

线程同步相关方法:

java 复制代码
public final void wait() throws InterruptedException;
public final native void notify();
public final native void notifyAll();
重要特性
  1. 所有类的超类:包括数组也继承自Object
  2. 可以存储任意对象:Object引用可以指向任何Java对象
  3. 数组也是对象:数组类型是隐式扩展Object的特殊类
完整示例
java 复制代码
public class Person implements Cloneable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);
        Person p3 = (Person) p1.clone();

        System.out.println(p1); // 自动调用toString()
        System.out.println("p1.equals(p2): " + p1.equals(p2));
        System.out.println("p1 == p2: " + (p1 == p2));
        System.out.println("p1.hashCode(): " + p1.hashCode());
        System.out.println("p2.hashCode(): " + p2.hashCode());
        System.out.println("p1.getClass(): " + p1.getClass());
        System.out.println("Clone: " + p3);
    }
}
最佳实践
  1. 总是重写toString() :提供有意义的对象描述
  2. 重写equals()时总要重写hashCode() :遵守两者协定
  3. 谨慎使用clone() :考虑使用拷贝构造器或工厂方法
  4. 避免使用finalize() :已被标记为@Deprecated
  5. 使用Objects工具类:Java 7+提供Objects.equals()等辅助方法

Object类是Java面向对象设计的基石,理解其方法对编写正确、高效的Java代码至关重要。

Objects

Objects 是 Java 7 引入的一个实用工具类,位于 java.util 包中,提供了一系列静态方法来操作对象或检查对象状态。这些方法大多是 null 安全的(null-tolerant),可以避免 NullPointerException。

主要方法
1. 对象判等
  • equals(Object a, Object b) - 安全地比较两个对象是否相等
  • deepEquals(Object a, Object b) - 深度比较两个对象(包括数组)
ini 复制代码
String str1 = null;
String str2 = "hello";

// 传统方式可能抛出NullPointerException
// boolean equal = str1.equals(str2); 

// 安全比较
boolean equal = Objects.equals(str1, str2); // false
2. 哈希码生成
  • hash(Object... values) - 为一系列输入值生成哈希码
  • hashCode(Object o) - 安全地获取对象的哈希码(null返回0)
ini 复制代码
String name = null;
int age = 30;

// 传统方式可能抛出NullPointerException
// int hash = name.hashCode() ^ age; 

// 安全哈希码生成
int hash = Objects.hash(name, age);
3. 对象检查
  • isNull(Object obj) - 检查对象是否为null
  • nonNull(Object obj) - 检查对象是否非null
  • requireNonNull(T obj) - 检查对象非null,否则抛出NullPointerException
  • requireNonNull(T obj, String message) - 带自定义错误消息的检查
ini 复制代码
String input = null;

// 检查null
if (Objects.isNull(input)) {
    System.out.println("Input is null");
}

// 要求非null
String value = Objects.requireNonNull(input, "Input cannot be null");
// 抛出NullPointerException: Input cannot be null
4. 字符串表示
  • toString(Object o) - 安全地调用对象的toString()
  • toString(Object o, String nullDefault) - 为null对象提供默认字符串
rust 复制代码
String str = null;

// 安全toString
System.out.println(Objects.toString(str)); // "null"
System.out.println(Objects.toString(str, "default")); // "default"
5. 比较
  • compare(T a, T b, Comparator<? super T> c) - 安全比较两个对象
ini 复制代码
String s1 = null;
String s2 = "java";

int result = Objects.compare(s1, s2, 
    Comparator.nullsFirst(Comparator.naturalOrder()));
// result为负数,因为null被认为小于非null值
使用场景
  1. 安全地处理可能为null的对象:避免NullPointerException
  2. 实现equals和hashCode方法:简化代码并提高安全性
  3. 参数验证:在方法开头验证参数非null
  4. 日志记录:安全地记录可能为null的对象信息
  5. 比较操作:进行null安全的比较
与Object类的区别
特性 Object类 Objects工具类
类型 所有类的超类 实用工具类
方法 基本对象方法 操作对象的实用方法
null处理 不处理null(会抛出NPE) 多数方法null安全
使用方式 通过对象实例调用 静态方法调用

Objects工具类极大地简化了null安全的对象操作,是现代Java编程中推荐使用的工具类之一。

BigInteger与BigDecimal

BigInteger

BigInteger 是 Java 中用于表示任意精度整数的类,位于 java.math 包中。它可以表示理论上无限大的整数(仅受内存限制),适用于基本数据类型(如 long)无法满足需求的大整数运算。

主要特点
  1. 不可变性:所有操作都返回新对象,原对象不变
  2. 任意精度:不受固定位数限制
  3. 丰富操作:提供各种数学运算方法
  4. 线程安全:由于其不可变性
创建BigInteger对象
1. 使用字符串创建
ini 复制代码
BigInteger bigInt1 = new BigInteger("123456789012345678901234567890");
2. 使用字节数组构造
ini 复制代码
byte[] bytes = {0x12, 0x34, 0x56, 0x78};
BigInteger bigInt2 = new BigInteger(bytes);
3. 使用静态工厂方法
ini 复制代码
BigInteger bigInt3 = BigInteger.valueOf(1234567890L);
常用方法
基本运算
ini 复制代码
BigInteger a = new BigInteger("123456789");
BigInteger b = new BigInteger("987654321");

// 加法
BigInteger sum = a.add(b);

// 减法
BigInteger difference = a.subtract(b);

// 乘法
BigInteger product = a.multiply(b);

// 除法
BigInteger quotient = a.divide(b);

// 取余
BigInteger remainder = a.remainder(b);

// 幂运算
BigInteger power = a.pow(3); // a的3次方
比较操作
css 复制代码
int comparison = a.compareTo(b); 
// 返回 -1(a<b), 0(a==b), 1(a>b)

boolean isEqual = a.equals(b); // 值相等性检查
位运算
ini 复制代码
BigInteger and = a.and(b);    // 按位与
BigInteger or = a.or(b);      // 按位或
BigInteger xor = a.xor(b);    // 按位异或
BigInteger not = a.not();     // 按位非
BigInteger shiftLeft = a.shiftLeft(2);  // 左移2位
BigInteger shiftRight = a.shiftRight(2); // 右移2位
数学运算
ini 复制代码
BigInteger gcd = a.gcd(b);    // 最大公约数
BigInteger mod = a.mod(b);    // 取模(结果非负)
BigInteger modPow = a.modPow(b, new BigInteger("100000")); // 模幂
BigInteger modInverse = a.modInverse(b); // 模逆元
类型转换
ini 复制代码
int intValue = a.intValue();
long longValue = a.longValue();
double doubleValue = a.doubleValue();
String stringValue = a.toString();
byte[] byteArray = a.toByteArray();
常量
ini 复制代码
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger ten = BigInteger.TEN;
完整示例
csharp 复制代码
import java.math.BigInteger;

public class BigIntegerExample {
    public static void main(String[] args) {
        // 创建BigInteger
        BigInteger a = new BigInteger("12345678901234567890");
        BigInteger b = BigInteger.valueOf(987654321L);
        
        // 基本运算
        System.out.println("a + b = " + a.add(b));
        System.out.println("a - b = " + a.subtract(b));
        System.out.println("a * b = " + a.multiply(b));
        System.out.println("a / b = " + a.divide(b));
        System.out.println("a % b = " + a.remainder(b));
        System.out.println("a^3 = " + a.pow(3));
        
        // 比较
        System.out.println("a.compareTo(b): " + a.compareTo(b));
        System.out.println("a.equals(b): " + a.equals(b));
        
        // 数学运算
        System.out.println("GCD: " + a.gcd(b));
        System.out.println("ModPow: " + a.modPow(b, new BigInteger("100000")));
        
        // 素数测试(概率性)
        System.out.println("Is probable prime: " + 
            a.isProbablePrime(100)); // 确定性参数
        
        // 转换
        System.out.println("Long value: " + b.longValue());
        System.out.println("String: " + a.toString(16)); // 16进制表示
    }
}
注意事项
  1. 性能考虑:BigInteger运算比基本数据类型慢
  2. 内存使用:大整数会消耗更多内存
  3. 不可变性:所有运算都返回新对象
  4. 异常处理:某些操作可能抛出ArithmeticException(如除以零)
  5. 素数测试:isProbablePrime()是概率性测试,参数越大准确性越高
实际应用场景
  1. 密码学(RSA等算法)
  2. 大数计算(如阶乘、斐波那契数列)
  3. 金融计算(需要高精度)
  4. 科学计算
  5. 需要超出long范围的整数运算

BigInteger类为Java提供了处理任意大小整数的能力,是处理大整数问题的理想选择。

BigDecimal

BigDecimal 是 Java 中用于高精度计算的类,位于 java.math 包中。它可以精确表示和计算浮点数,避免了 floatdouble 类型在计算时可能出现的精度问题。

主要特点
  1. 任意精度:可以表示任意精度的十进制数
  2. 不可变性:所有运算都返回新对象,原对象不变
  3. 精确计算:解决了浮点数计算中的精度问题
  4. 舍入控制:提供多种舍入模式
  5. 线程安全:由于其不可变性
创建BigDecimal对象
1. 使用字符串构造(推荐)
ini 复制代码
BigDecimal bd1 = new BigDecimal("0.1"); // 精确表示0.1
2. 使用double构造(不推荐,可能有精度问题)
ini 复制代码
BigDecimal bd2 = new BigDecimal(0.1); // 实际值为0.100000000000000005551115...
3. 使用静态工厂方法
ini 复制代码
BigDecimal bd3 = BigDecimal.valueOf(0.1); // 内部使用字符串构造
BigDecimal bd4 = BigDecimal.valueOf(123456789L); // 从long创建
常用方法
基本运算
ini 复制代码
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3.2");

// 加法
BigDecimal sum = a.add(b);

// 减法
BigDecimal difference = a.subtract(b);

// 乘法
BigDecimal product = a.multiply(b);

// 除法(需要指定舍入模式)
BigDecimal quotient = a.divide(b, 2, RoundingMode.HALF_UP);

// 取余
BigDecimal remainder = a.remainder(b);
比较操作
css 复制代码
int comparison = a.compareTo(b); 
// 返回 -1(a<b), 0(a==b), 1(a>b)

boolean isEqual = a.equals(b); // 值相等性检查(包括精度)
舍入控制
ini 复制代码
BigDecimal rounded = a.setScale(2, RoundingMode.HALF_UP); // 四舍五入保留2位小数
数学运算
ini 复制代码
BigDecimal absValue = a.abs();       // 绝对值
BigDecimal negated = a.negate();     // 取反
BigDecimal power = a.pow(3);         // 幂运算
BigDecimal sqrt = a.sqrt(MathContext.DECIMAL32); // 平方根
类型转换
ini 复制代码
int intValue = a.intValue();
long longValue = a.longValue();
double doubleValue = a.doubleValue();
String stringValue = a.toString();
舍入模式
模式 描述
UP 远离零方向舍入
DOWN 向零方向舍入
CEILING 向正无穷方向舍入
FLOOR 向负无穷方向舍入
HALF_UP 四舍五入(>=0.5向上)
HALF_DOWN 五舍六入(>0.5向上)
HALF_EVEN 银行家舍入法(向最近的偶数舍入)
UNNECESSARY 不需要舍入(精确值)
完整示例
复制代码

public static void main(String[] args) { // 创建BigDecimal(推荐使用字符串构造) BigDecimal price = new BigDecimal("19.99"); BigDecimal quantity = new BigDecimal("2.5"); BigDecimal taxRate = new BigDecimal("0.0825"); // 8.25%

ini 复制代码
// 计算总金额(价格×数量)
BigDecimal subtotal = price.multiply(quantity);
System.out.println("小计: $" + subtotal.setScale(2, RoundingMode.HALF_UP));

// 计算税费
BigDecimal tax = subtotal.multiply(taxRate)
                       .setScale(2, RoundingMode.HALF_UP);
System.out.println("税费: $" + tax);

// 计算总金额
BigDecimal total = subtotal.add(tax);
System.out.println("总计: $" + total.setScale(2, RoundingMode.HALF_UP));

// 比较
BigDecimal otherPrice = new BigDecimal("20.00");
System.out.println("compareTo比较结果: " + price.compareTo(otherPrice)); // -1
BigDecimal price1 = new BigDecimal("19.9900");
System.out.println("equals比较结果: " + price.equals(price1)); //equals比较值和精度
// 精度控制
BigDecimal pi = new BigDecimal("3.141592653589793");
System.out.println("PI (2位小数): " + pi.setScale(2, RoundingMode.HALF_UP));
System.out.println("PI (4位小数): " + pi.setScale(4, RoundingMode.HALF_UP));

// 除法示例
BigDecimal dividend = new BigDecimal("10");
BigDecimal divisor = new BigDecimal("3");
System.out.println("10/3 (精确): " + 
    dividend.divide(divisor, 10, RoundingMode.HALF_UP));

}

复制代码
注意事项
  1. 构造方法选择:优先使用字符串构造,避免double构造的精度问题
  2. 除法运算:必须指定舍入模式或精度,否则可能抛出ArithmeticException
  3. 性能考虑:BigDecimal运算比基本数据类型慢
  4. 不可变性:所有运算都返回新对象
  5. equals与compareTo:equals比较值和精度,compareTo仅比较值
实际应用场景
  1. 金融计算(货币、利率等)
  2. 科学计算(需要高精度)
  3. 统计计算
  4. 任何需要精确小数运算的场景
  5. 避免浮点数精度问题的场景

BigDecimal类为Java提供了精确的十进制运算能力,是处理财务计算和其他需要高精度计算的理想选择。

正则表达式

正则表达式(Regular Expression)是一种强大的文本处理工具,Java通过java.util.regex包提供了对正则表达式的支持。下面详细介绍Java中正则表达式的使用。

1. 核心类

Java正则表达式主要涉及三个类:

  • Pattern:正则表达式的编译表示
  • Matcher:通过解释Pattern对字符序列执行匹配操作的引擎
  • PatternSyntaxException:正则表达式语法异常

2. 基本使用步骤

2.1 编译正则表达式
ini 复制代码
Pattern pattern = Pattern.compile("正则表达式");
2.2 创建匹配器
ini 复制代码
Matcher matcher = pattern.matcher("要匹配的字符串");
2.3 执行匹配操作
ini 复制代码
boolean matches = matcher.matches();  // 全词匹配
boolean find = matcher.find();       // 查找子串

3. 常用匹配方法

3.1 全词匹配
ini 复制代码
String regex = "a*b";
boolean isMatch = Pattern.matches(regex, "aaaaab"); // true
3.2 查找匹配
csharp 复制代码
Pattern pattern = Pattern.compile("\\d+");  // 匹配数字
Matcher matcher = pattern.matcher("abc123def456");
while (matcher.find()) {
    System.out.println("找到: " + matcher.group());
}
// 输出:
// 找到: 123
// 找到: 456
3.3 分组匹配
csharp 复制代码
Pattern pattern = Pattern.compile("(\\d{3})-(\\d{2})");
Matcher matcher = pattern.matcher("123-45");
if (matcher.matches()) {
    System.out.println("组1: " + matcher.group(1)); // 123
    System.out.println("组2: " + matcher.group(2)); // 45
}

4. 常用正则表达式元字符

| 元字符 | 描述 |
|-----------|---------------------------|-----|
| . | 匹配任意单个字符(除换行符) |
| \d | 数字[0-9] |
| \D | 非数字[^0-9] |
| \s | 空白字符[\t\n\x0B\f\r] |
| \S | 非空白字符[^\s] |
| \w | 单词字符[a-zA-Z_0-9] |
| \W | 非单词字符[^\w] |
| \W | 行开头 |
| $ | 行结尾 |
| * | 0次或多次 |
| + | 1次或多次 |
| ? | 0次或1次 |
| {n} | 恰好n次 |
| {n,} | 至少n次 |
| {n,m} | n到m次 |
| [...] | 字符集合 |
| [^...] | 否定字符集合 |
| | | 或操作 |

5. 常用正则表达式示例

5.1 验证邮箱
ini 复制代码
String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
Pattern pattern = Pattern.compile(emailRegex);
System.out.println(pattern.matcher("[email protected]").matches()); // true
5.2 验证手机号
ini 复制代码
String phoneRegex = "^1[3-9]\\d{9}$";
System.out.println("13812345678".matches(phoneRegex)); // true
5.3 提取HTML标签内容
ini 复制代码
String html = "<h1>标题</h1><p>内容</p>";
Pattern tagPattern = Pattern.compile("<([a-z][a-z0-9]*)[^>]*>(.*?)</\\1>");
Matcher tagMatcher = tagPattern.matcher(html);
while (tagMatcher.find()) {
    System.out.println("标签: " + tagMatcher.group(1) + ", 内容: " + tagMatcher.group(2));
}

6. 字符串类中的正则方法

String类也提供了一些基于正则表达式的方法:

ini 复制代码
// 分割字符串
String[] parts = "a,b,c".split(",");

// 替换
String newStr = "a1b2c3".replaceAll("\\d", "-"); // "a-b-c-"

// 匹配检查
boolean isMatch = "123".matches("\\d+"); // true

7. 高级特性

7.1 非贪婪匹配
ini 复制代码
// 贪婪匹配
Pattern greedy = Pattern.compile("a.*b");
Matcher m1 = greedy.matcher("aabab");
m1.find();
System.out.println(m1.group()); // aabab

// 非贪婪匹配
Pattern reluctant = Pattern.compile("a.*?b");
Matcher m2 = reluctant.matcher("aabab");
m2.find();
System.out.println(m2.group()); // aab
7.2 前后查找
ini 复制代码
// 正向肯定预查
Pattern pattern = Pattern.compile("Windows(?=95|98|NT)");
Matcher matcher = pattern.matcher("Windows98");
System.out.println(matcher.find()); // true

// 正向否定预查
pattern = Pattern.compile("Windows(?!95|98|NT)");
matcher = pattern.matcher("WindowsXP");
System.out.println(matcher.find()); // true

8. 性能优化建议

  1. 预编译Pattern对象并重用
  2. 避免过度复杂的正则表达式
  3. 考虑使用非捕获组(?:...)提高性能
  4. 对于简单匹配,优先使用String类的方法

Java正则表达式功能强大,可以处理各种复杂的文本匹配和替换需求,是Java开发中处理文本的重要工具。

时间类

JDK7

在JDK7及之前版本中,Java提供了以下几个主要的时间处理类:

1. java.util.Date

Date类是Java最早引入的时间处理类,位于java.util包中。
主要特点

  • 表示特定的瞬间,精确到毫秒
  • 从1970年1月1日00:00:00 GMT(Unix纪元)开始计算
  • 大部分方法已过时(deprecated)

常用方法

ini 复制代码
Date date = new Date(); // 当前时间
long time = date.getTime(); // 获取毫秒数
date.setTime(time); // 设置时间

问题

  • 年份从1900年开始计算
  • 月份从0开始(0表示一月)
  • 线程不安全
  • 设计混乱,很多方法已过时
2. java.util.Calendar

Calendar类是为了解决Date类的不足而引入的抽象类,常用的实现类是GregorianCalendar
主要特点

  • 提供更丰富的日期时间操作
  • 支持时区
  • 仍然是可变对象

常用方法

ini 复制代码
Calendar calendar = Calendar.getInstance(); // 默认时区的当前时间
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH); // 0-11
int day = calendar.get(Calendar.DAY_OF_MONTH);

calendar.add(Calendar.DAY_OF_MONTH, 1); // 增加一天
calendar.set(Calendar.YEAR, 2020); // 设置年份

问题

  • 月份仍然从0开始
  • 性能较差
  • 代码冗长
  • 仍然是可变对象
3. java.text.SimpleDateFormat

用于格式化和解析日期时间。
常用方法

ini 复制代码
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf.format(new Date()); // 日期转字符串
Date parsedDate = sdf.parse("2020-01-01 12:00:00"); // 字符串转日期

问题

  • 线程不安全(不能在多线程中共享实例)
  • 解析不严格(如"2020-02-30"会被解析为2020-03-01)
4. java.sql.Date/Timestamp/Time

这些是JDBC相关的日期时间类:

  • java.sql.Date - 只包含日期部分
  • java.sql.Time - 只包含时间部分
  • java.sql.Timestamp - 包含日期和时间,精确到纳秒
JDK7之前时间类的缺点
  1. 设计混乱Date类同时包含日期和时间,但又有单独的java.sql.Date只表示日期
  2. 可变性:所有类都是可变的,不适合在多线程环境中使用
  3. 月份从0开始:容易导致错误
  4. 时区处理复杂:需要手动处理时区转换
  5. 线程不安全 :如SimpleDateFormat
  6. 扩展性差:难以添加新的日历系统

正是由于这些问题,Java在JDK8中引入了全新的java.time包(JSR 310),提供了更现代、更合理的时间日期API。

JDK8

JDK8 引入了全新的日期时间 API(JSR 310),位于 java.time 包中,解决了旧 API(Date、Calendar 等)的各种问题,提供了更清晰、更易用、线程安全的日期时间处理方式。

核心类
1. 主要日期时间类
类名 描述 示例值
LocalDate 只包含日期(年-月-日) 2023-05-20
LocalTime 只包含时间(时:分:秒.纳秒) 14:30:15.123
LocalDateTime 包含日期和时间 2023-05-20T14:30:15
ZonedDateTime 包含日期、时间和时区 2023-05-20T14:30:15+08:00[Asia/Shanghai]
Instant 时间戳(从1970-01-01T00:00:00Z开始的秒/纳秒) 1684578615.123456789
2. 时段和周期类
类名 描述
Duration 时间间隔(精确到纳秒),用于 LocalTime、Instant
Period 日期间隔(年、月、日),用于 LocalDate
3. 其他实用类
类名 描述
DateTimeFormatter 替代 SimpleDateFormat,线程安全
ZoneId 时区标识(如 "Asia/Shanghai")
Clock 用于获取当前时刻的时钟
使用示例
创建对象
ini 复制代码
// 当前日期
LocalDate today = LocalDate.now();

// 指定日期
LocalDate birthday = LocalDate.of(1990, Month.MAY, 20);

// 当前时间
LocalTime now = LocalTime.now();

// 指定时间
LocalTime lunchTime = LocalTime.of(12, 30);

// 当前日期时间
LocalDateTime current = LocalDateTime.now();

// 指定日期时间
LocalDateTime meeting = LocalDateTime.of(2023, 6, 15, 14, 30);

// 带时区的日期时间
ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

// 时间戳
Instant instant = Instant.now();
日期时间操作
ini 复制代码
LocalDate tomorrow = today.plusDays(1);
LocalTime anHourLater = now.plusHours(1);
LocalDateTime nextWeek = current.plusWeeks(1);

// 使用 Period 和 Duration
Period tenDays = Period.ofDays(10);
LocalDate inTenDays = today.plus(tenDays);

Duration twoHours = Duration.ofHours(2);
LocalTime later = now.plus(twoHours);
日期时间比较
ini 复制代码
boolean isAfter = today.isAfter(birthday);
boolean isBefore = now.isBefore(lunchTime);
boolean isEqual = current.isEqual(meeting);
格式化与解析
ini 复制代码
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

// 格式化
String formatted = current.format(formatter); // "2023-05-20 14:30:15"

// 解析
LocalDateTime parsed = LocalDateTime.parse("2023-05-20 14:30:15", formatter);
与旧API转换
scss 复制代码
// Date 转 Instant
Instant instant = new Date().toInstant();

// Instant 转 Date
Date date = Date.from(Instant.now());

// Calendar 转 ZonedDateTime
ZonedDateTime zdt = Calendar.getInstance().toInstant()
    .atZone(ZoneId.systemDefault());
主要优势
  1. 清晰的设计:分离日期、时间、日期时间等概念
  2. 不可变且线程安全:所有类都是不可变的
  3. 流畅的API:方法链式调用更直观
  4. 更好的时区处理:明确区分本地时间和带时区时间
  5. 扩展性强:支持自定义日历系统
  6. 月份从1开始:更符合人类习惯

新的 java.time API 已经成为 Java 处理日期时间的标准方式,推荐在新项目中使用它替代旧的 DateCalendar 类。

包装类

Java 包装类是为八种基本数据类型提供的对象表示形式,位于 java.lang 包中。它们将基本类型"包装"成对象,使得基本类型可以像对象一样操作。

包装类与基本类型的对应关系

基本数据类型 包装类 继承关系
byte Byte extends Number
short Short extends Number
int Integer extends Number
long Long extends Number
float Float extends Number
double Double extends Number
char Character 不继承Number(特殊处理)
boolean Boolean 不继承Number(特殊处理)

包装类的主要用途

  1. 在集合中使用:集合类(如ArrayList)只能存储对象,不能存储基本类型
  2. 提供实用方法:如类型转换、进制转换等
  3. 允许null值:基本类型不能为null,包装类可以
  4. 泛型支持:泛型类型参数必须是类类型

自动装箱与拆箱(Autoboxing & Unboxing)

JDK5 引入了自动装箱和拆箱机制:

ini 复制代码
// 自动装箱:基本类型 -> 包装类(编译器自动转换)
Integer i = 10;     // 等价于 Integer i = Integer.valueOf(10);

// 自动拆箱:包装类 -> 基本类型
int n = i;          // 等价于 int n = i.intValue();

常用方法

1. 构造方法(JDK9后已废弃,推荐使用valueOf())
ini 复制代码
Integer num = new Integer(10);      // 已废弃
Integer num = Integer.valueOf(10);  // 推荐方式
2. 类型转换
ini 复制代码
// 字符串转数值
int i = Integer.parseInt("123");       // 返回int
Integer i = Integer.valueOf("123");    // 返回Integer

// 数值转字符串
String s = Integer.toString(123);
String s = 123 + "";                   // 简便方式

// 其他进制转换
String binary = Integer.toBinaryString(10);   // 1010
String hex = Integer.toHexString(255);       // ff
3. 比较方法
css 复制代码
Integer a = 100;
Integer b = 100;

a.equals(b);    // true - 比较值
a == b;         // true (在-128~127范围内为true,超出此范围则为false)
a.compareTo(b); // 0 (相等), 正数(a>b), 负数(a<b)

注意事项

  1. 缓存机制:包装类对常用值(-128~127)有缓存,valueOf()会返回缓存对象
ini 复制代码
Integer a = 127;
Integer b = 127;
a == b; // true (同一对象)

Integer c = 128;
Integer d = 128;
c == d; // false (不同对象)
  1. NPE风险:自动拆箱时如果包装类为null会抛出NullPointerException
ini 复制代码
Integer num = null;
int n = num; // 抛出NullPointerException
  1. 性能考虑:包装类比基本类型占用更多内存,操作也更耗时

各包装类特有方法

Character 类特有方法
arduino 复制代码
Character.isDigit('9');    // 是否数字
Character.isLetter('a');   // 是否字母
Character.isWhitespace(' '); // 是否空白字符
Character.toUpperCase('a'); // 转大写
Boolean 类特有方法
javascript 复制代码
Boolean.parseBoolean("true");  // 字符串转boolean
Boolean.TRUE;                 // 预定义常量
Number 类方法

所有数值包装类的父类Number提供的方法:

scss 复制代码
byteValue(), shortValue(), intValue(), 
longValue(), floatValue(), doubleValue()

最佳实践

  1. 优先使用基本类型(性能更好)
  2. 需要对象表示时使用包装类(如集合、泛型)
  3. 比较包装类时使用equals()而非==
  4. 注意自动拆箱时的NPE风险
  5. JDK9+推荐使用valueOf()而非构造函数

包装类在Java中扮演着重要角色,特别是在集合框架和面向对象编程中,理解它们的特性和正确使用方法对于编写健壮的Java代码非常重要。

Arrays工具类

java.util.Arrays 是 Java 中专门用于操作数组的工具类,提供了各种静态方法来操作数组(排序、搜索、比较、填充等)。这个工具类在 JDK 1.2 引入,并随着 Java 版本更新不断增加了新方法。

一、核心功能概览

功能类别 主要方法
排序 sort(), parallelSort()
搜索 binarySearch()
比较 equals(), deepEquals()
填充 fill(), setAll(), parallelSetAll()
转换 asList(), toString(), deepToString()
复制 copyOf(), copyOfRange()
流操作 stream()
并行处理 parallelPrefix()
哈希计算 hashCode(), deepHashCode()
新特性 mismatch() (JDK9), compare()/compareUnsigned() (JDK9)

二、常用方法详解

1. 排序方法
ini 复制代码
// 基本类型数组排序
int[] intArr = {3, 1, 4, 1, 5};
Arrays.sort(intArr); // [1, 1, 3, 4, 5]

// 并行排序(大数据量更高效)
Arrays.parallelSort(intArr);

// 对象数组排序(需实现Comparable或提供Comparator)
String[] strArr = {"banana", "apple", "pear"};
Arrays.sort(strArr); // ["apple", "banana", "pear"]
Arrays.sort(strArr, Comparator.reverseOrder()); // 逆序

// 部分排序
Arrays.sort(intArr, 1, 4); // 只排序索引1到3的元素
2. 二分查找
ini 复制代码
// 必须先排序!
int[] sortedArr = {1, 3, 5, 7, 9};
int index = Arrays.binarySearch(sortedArr, 5); // 返回2
int notFound = Arrays.binarySearch(sortedArr, 4); // 返回-3 (插入点为2+1)

// 对象数组搜索
String[] fruits = {"apple", "banana", "pear"};
int pos = Arrays.binarySearch(fruits, "pear"); // 2
3.数组比较
ini 复制代码
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
int[] c = {1, 3, 2};

boolean eq1 = Arrays.equals(a, b); // true
boolean eq2 = Arrays.equals(a, c); // false

// 多维数组比较
int[][] deep1 = {{1,2}, {3,4}};
int[][] deep2 = {{1,2}, {3,4}};
boolean deepEq = Arrays.deepEquals(deep1, deep2); // true
4. 数组填充
scss 复制代码
int[] arr = new int[5];
Arrays.fill(arr, 1); // [1, 1, 1, 1, 1]

// 部分填充
Arrays.fill(arr, 1, 3, 9); // [1, 9, 9, 1, 1]

// 使用生成函数填充
Arrays.setAll(arr, i -> i * 2); // [0, 2, 4, 6, 8]
Arrays.parallelSetAll(arr, i -> i * i); // [0, 1, 4, 9, 16]
5. 数组复制
ini 复制代码
int[] original = {1, 2, 3, 4, 5};

// 完整/截断复制
int[] copy1 = Arrays.copyOf(original, 3); // [1, 2, 3]
int[] copy2 = Arrays.copyOf(original, 7); // [1,2,3,4,5,0,0]

// 范围复制
int[] rangeCopy = Arrays.copyOfRange(original, 1, 4); // [2, 3, 4]
6. 数组转字符串
ini 复制代码
int[] arr = {1, 2, 3};
System.out.println(Arrays.toString(arr)); // [1, 2, 3]

int[][] deepArr = {{1,2}, {3,4}};
System.out.println(Arrays.deepToString(deepArr)); // [[1, 2], [3, 4]]
7. 数组转List
ini 复制代码
String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr); // 固定大小列表

// 注意:返回的ArrayList是Arrays的内部类,不是java.util.ArrayList
list.add("d"); // 抛出UnsupportedOperationException
8. Java8+新增方法
ini 复制代码
// 数组流处理
int[] numbers = {1, 2, 3};
int sum = Arrays.stream(numbers).sum();

// 并行前缀计算(累积和)
int[] arr = {1, 2, 3, 4};
Arrays.parallelPrefix(arr, (a, b) -> a + b); // [1, 3, 6, 10]

// JDK9: 查找第一个不匹配的索引
int[] a = {1, 2, 3};
int[] b = {1, 2, 4};
int mismatch = Arrays.mismatch(a, b); // 2

// JDK9: 数组比较
int compare = Arrays.compare(a, b); // 负数(a<b)

三、性能注意事项

  1. sort() vs parallelSort()

    • 小数组(长度 < 2^13):sort() 更快
    • 大数组:parallelSort() 利用多核优势
  2. binarySearch() 前提

    • 必须对数组先排序,否则结果未定义
  3. asList() 的限制

    • 返回的列表大小固定
    • 修改原始数组会影响列表
  4. 基本类型 vs 对象数组

    • 基本类型方法有专门优化(避免装箱开销)

四、实际应用示例

示例1:统计成绩
ini 复制代码
double[] scores = {85.5, 92.0, 76.5, 88.0};
Arrays.sort(scores); // 排序
double average = Arrays.stream(scores).average().orElse(0);
示例2:矩阵操作
scss 复制代码
int[][] matrix = new int[3][3];
Arrays.stream(matrix).forEach(row -> Arrays.fill(row, 1)); // 填充1
示例3:数据验证
ini 复制代码
String[] validCodes = {"A1", "B2", "C3"};
Arrays.sort(validCodes); // 二分查找需要先排序
boolean isValid = Arrays.binarySearch(validCodes, inputCode) >= 0;

五、总结

Arrays 工具类提供了:

  • 丰富的数组操作方法
  • 对基本类型和对象数组的分别处理
  • 逐步增强的并行处理能力
  • Java 8+ 的流式集成

最佳实践:

  1. 大数据集考虑使用并行方法(parallelSort等)
  2. 优先使用专门的基本类型方法(避免自动装箱)
  3. 注意asList()等方法的特殊行为
  4. 保持数组排序以便使用二分查找

Lambda表达式

Lambda 表达式是 Java 8 引入的最重要特性之一,它极大地简化了函数式编程在 Java 中的实现方式,使代码更加简洁、灵活。

一、Lambda 表达式基础

1. 基本语法
rust 复制代码
(parameters) -> expression
或
(parameters) -> { statements; }
2. 核心特征
  • 匿名:没有显式的名称
  • 函数式:属于某个函数式接口
  • 简洁:比匿名类更紧凑
  • 可传递:可以作为参数传递或存储在变量中
3. 组件解析
部分 说明
参数列表 可以省略参数类型(编译器推断),空参数使用()
箭头符号 -> 分隔参数和Lambda体
Lambda体 单个表达式(隐含return)或代码块(需要显式return)

二、Lambda 表达式示例

1. 不同形式的Lambda
ini 复制代码
// 1. 无参数
Runnable r = () -> System.out.println("Hello");

// 2. 单参数,可省略括号
Consumer<String> c = s -> System.out.println(s);

// 3. 多参数
Comparator<Integer> comp = (a, b) -> a.compareTo(b);

// 4. 显式声明参数类型
BinaryOperator<Long> add = (Long x, Long y) -> x + y;

// 5. 多行代码块
Function<String, Integer> f = s -> {
    int len = s.length();
    return len * 2;
};
2. 方法引用(更简洁的Lambda)
javascript 复制代码
// 静态方法引用
Function<String, Integer> p = Integer::parseInt;

// 实例方法引用
Consumer<String> printer = System.out::println;

// 任意对象的实例方法引用
Function<String, String> upper = String::toUpperCase;

// 构造方法引用
Supplier<List<String>> listSupplier = ArrayList::new;

三、函数式接口

1. 核心函数式接口
接口 方法签名 用途
Supplier<T> T get() 提供值(工厂)
Consumer<T> void accept(T t) 消费值(操作)
Function<T,R> R apply(T t) 转换值(映射)
Predicate<T> boolean test(T t) 测试值(过滤)
UnaryOperator<T> T apply(T t) 一元运算(继承Function)
BinaryOperator<T> T apply(T t1, T t2) 二元运算(继承BiFunction)
2. 自定义函数式接口
scss 复制代码
@FunctionalInterface
interface StringProcessor {
    String process(String input);
    
    // 可以有默认方法
    default void info() {
        System.out.println("String processor");
    }
}

StringProcessor sp = s -> s.toUpperCase();

四、Lambda 实际应用

1. 集合操作
ini 复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 遍历
names.forEach(name -> System.out.println(name));

// 过滤
List<String> longNames = names.stream()
                             .filter(n -> n.length() > 4)
                             .collect(Collectors.toList());

// 映射
List<Integer> lengths = names.stream()
                            .map(String::length)
                            .collect(Collectors.toList());
2. 线程初始化
csharp 复制代码
// 传统方式
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Running");
    }
}).start();

// Lambda方式
new Thread(() -> System.out.println("Running")).start();
3. 事件处理
less 复制代码
button.addActionListener(e -> System.out.println("Button clicked"));
4. 排序比较
ini 复制代码
List<Person> people = ...;
people.sort((p1, p2) -> p1.getAge() - p2.getAge());

// 更简洁的方式
people.sort(Comparator.comparingInt(Person::getAge));

五、Lambda 高级特性

1. 变量捕获

Lambda可以捕获:

  • 实例变量和静态变量(无限制)
  • 局部变量(必须为final或等效final)
ini 复制代码
int limit = 10; // 等效final
Runnable r = () -> {
    for (int i = 0; i < limit; i++) {
        System.out.println(i);
    }
};
2. 方法引用类型
类型 语法示例 对应的Lambda表达式
静态方法引用 ClassName::staticMethod (args) -> ClassName.staticMethod(args)
实例方法引用(特定对象) instance::method (args) -> instance.method(args)
实例方法引用(任意对象) ClassName::method (obj, args) -> obj.method(args)
构造方法引用 ClassName::new (args) -> new ClassName(args)
3. 组合Lambda
ini 复制代码
Predicate<String> startsWithA = s -> s.startsWith("A");
Predicate<String> endsWithZ = s -> s.endsWith("Z");

// 组合谓词
Predicate<String> startsWithAAndEndsWithZ = startsWithA.and(endsWithZ);

Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, Integer> add3 = x -> x + 3;

// 函数组合
Function<Integer, Integer> multiplyThenAdd = multiplyBy2.andThen(add3);
Function<Integer, Integer> addThenMultiply = multiplyBy2.compose(add3);

六、Lambda 注意事项

  1. 性能考虑

    • Lambda首次调用会有初始化开销
    • 简单操作可能不如传统方式高效
    • 高频调用场景需测试性能
  2. 调试困难

    • 匿名特性使调试栈信息不直观
    • 复杂Lambda可提取为方法引用
  3. 过度使用问题

    • 复杂业务逻辑不适合用Lambda
    • 多行Lambda影响可读性
  4. 序列化限制

    • Lambda表达式默认不可序列化
    • 需要实现Serializable接口的特殊处理

七、Java后续版本增强

Java 8+
  • 引入java.util.function
  • 新增Stream API配合Lambda使用
Java 11
  • 允许var用于Lambda参数:
csharp 复制代码
(var x, var y) -> x + y

Lambda表达式极大地改变了Java的编程范式,使函数式编程风格与面向对象风格能够和谐共存。合理使用Lambda可以使代码更简洁、更富有表达力,但也需要注意不要过度使用导致代码可读性下降。

相关推荐
吴生439618 分钟前
数据库ALGORITHM = INSTANT 特性研究过程
后端
程序猿chen33 分钟前
JVM考古现场(十九):量子封神·用鸿蒙编译器重铸天道法则
java·jvm·git·后端·程序人生·java-ee·restful
Chandler241 小时前
Go:接口
开发语言·后端·golang
ErizJ1 小时前
Golang|Channel 相关用法理解
开发语言·后端·golang
automan021 小时前
golang 在windows 系统的交叉编译
开发语言·后端·golang
Pandaconda1 小时前
【新人系列】Golang 入门(十三):结构体 - 下
后端·golang·go·方法·结构体·后端开发·值传递
我是谁的程序员1 小时前
Flutter iOS真机调试报错弹窗:不受信任的开发者
后端
蓝宝石Kaze1 小时前
使用 Viper 读取配置文件
后端
aiopencode1 小时前
Flutter 开发指南:安卓真机、虚拟机调试及 VS Code 开发环境搭建
后端
开心猴爷1 小时前
M1搭建flutter环境+真机调试demo
后端