Lambda表达式 算法异常

Lambda

1. 核心定义

Lambda表达式是Java 8引入的新特性,本质是匿名函数(没有方法名、修饰符和返回值类型),用于简化函数式接口的实现,让代码更简洁、紧凑,专注于"做什么"而非"怎么实现"。

核心前提:Lambda表达式只能用于实现函数式接口(只有一个抽象方法的接口,可通过@FunctionalInterface注解校验)。

2. 语法格式

基础格式:(参数列表) -> { 方法体 }

说明:

  • 参数列表:参数类型可省略(类型推断),多个参数用逗号分隔,无参数则写();

  • ->:箭头符号,用于分隔参数列表和方法体;

  • 方法体:单个语句可省略{}和return(若有返回值),多个语句必须用{}包裹,且需显式写return。

3. 常见简化写法(示例)

以函数式接口Runnable(无参无返回)、Comparator(有参有返回)为例:

  • 原始匿名内部类写法: // Runnable接口实现 ``Runnable runnable = new Runnable() { `` @Override `` public void run() { `` System.out.println("匿名内部类执行"); `` } ``};

  • Lambda简化(无参无返回,方法体单语句): Runnable runnable = () -> System.out.println("Lambda执行");

  • 有参有返回(Comparator排序,省略参数类型+方法体单语句省略return): // 原始写法 ``Comparator<Integer> comparator = new Comparator<Integer>() { `` @Override `` public int compare(Integer a, Integer b) { `` return a - b; `` } ``}; ``// Lambda简化 ``Comparator<Integer> comparator = (a, b) -> a - b;

4. 核心注意事项

  • Lambda表达式没有自己的this和super,其this指向外层包围类的对象;

  • Lambda表达式中引用的外部变量,必须是final或事实上的final(即变量声明后未被修改);

  • Lambda表达式不能单独存在,必须赋值给函数式接口变量,或作为方法参数传递。

二、方法引用

1. 核心定义

方法引用是Lambda表达式的"语法糖",当Lambda表达式的方法体,只是调用一个已存在的方法(无需额外逻辑)时,可通过方法引用简化写法,让代码更简洁、可读性更强。

核心逻辑:方法引用本质是"引用一个方法,代替Lambda的方法体",其签名(参数列表、返回值)必须与函数式接口的抽象方法签名一致。

2. 语法格式

方法引用的格式分为4种,核心是类名/对象名 :: 方法名(::为方法引用运算符),具体如下:

(1)对象::实例方法

场景:调用某个对象的实例方法,Lambda的参数列表与该实例方法的参数列表一致。

复制代码
// 示例:调用String对象的length()方法(无参有返回)
// Lambda写法
Function<String, Integer> function = s -> s.length();
// 方法引用写法(String对象s的实例方法length)
Function<String, Integer> function = String::length;

(2)类::静态方法

场景:调用某个类的静态方法,Lambda的参数列表与该静态方法的参数列表一致。

复制代码
// 示例:调用Integer类的parseInt()方法(有参有返回)
// Lambda写法
Function<String, Integer> function = s -> Integer.parseInt(s);
// 方法引用写法(Integer类的静态方法parseInt)
Function<String, Integer> function = Integer::parseInt;

(3)类::实例方法

场景:调用某个类的实例方法,但Lambda的第一个参数是该类的对象(即方法的调用者),后续参数是该实例方法的参数。

复制代码
// 示例:调用String类的equals()方法(有参有返回,第一个参数是调用者)
// Lambda写法
BiFunction<String, String, Boolean> biFunction = (s1, s2) -> s1.equals(s2);
// 方法引用写法(String类的实例方法equals,s1是调用者)
BiFunction<String, String, Boolean> biFunction = String::equals;

(4)构造器引用:类::new

场景:Lambda的方法体是创建一个对象(调用构造器),Lambda的参数列表与该构造器的参数列表一致。

复制代码
// 示例:调用String的构造器(String(char[] value))
// Lambda写法
Function<char[], String> function = chars -> new String(chars);
// 构造器引用写法
Function<char[], String> function = String::new;

3. 核心注意事项

  • 方法引用不能单独使用,必须配合函数式接口,且方法签名(参数、返回值)需与接口抽象方法一致;

  • 方法引用是Lambda的简化,只有当Lambda方法体仅调用一个现有方法时,才能使用;

  • 构造器引用本质是"引用构造器",等价于Lambda中new对象的逻辑,支持重载(根据函数式接口的抽象方法签名匹配对应构造器)。

三、Lambda与方法引用的关联

  1. 方法引用是Lambda的简化形式,所有方法引用都能转化为对应的Lambda表达式,但反之不一定(Lambda方法体有复杂逻辑时,无法用方法引用);

  2. 两者的核心目的一致:简化函数式接口的实现,减少冗余代码,提升代码可读性和简洁性;

  3. 使用优先级:能使用方法引用时,优先使用(更简洁);Lambda适合方法体有自定义逻辑的场景。

四、核心总结

  • Lambda:匿名函数,简化函数式接口实现,格式为 (参数) -> 方法体;

  • 方法引用:Lambda的语法糖,格式为 类名/对象名::方法名,分4种场景;

  • 核心前提:两者都依赖函数式接口(仅一个抽象方法)。

算法

1. 核心定义

算法是解决特定问题的步骤集合,是对问题求解过程的精准描述,具有明确的输入、输出和有限性(步骤有限且可终止)、确定性(每一步操作唯一)、可行性(每一步可通过有限操作实现)的特点。

简单来说,算法就是"解决问题的思路和步骤",比如计算两数之和、排序数组,都有对应的算法。

2. 算法的核心特性(必记)

  • 输入:算法有0个或多个输入(如排序算法需要输入待排序数组);

  • 输出:算法至少有1个输出(求解结果),输出与输入对应;

  • 有限性:算法的步骤是有限的,不会无限循环,最终会终止;

  • 确定性:每一步操作都有明确的含义,不会出现歧义;

  • 可行性:每一步操作都可以通过计算机或人工有限次执行完成。

3. 常见基础算法(入门必备)

(1)排序算法(最常用)

核心目的:将一组数据按指定顺序(升序/降序)排列,重点掌握3种基础排序:

  • 冒泡排序 :通过相邻元素两两比较、交换,将最大/最小元素逐步"冒泡"到数组末尾,简单易理解,效率较低(适合少量数据)。 // 冒泡排序示例(升序) ``public static void bubbleSort(int[] arr) { `` int n = arr.length; `` for (int i = 0; i < n - 1; i++) { `` for (int j = 0; j < n - 1 - i; j++) { `` if (arr[j] > arr[j + 1]) { `` // 交换相邻元素 `` int temp = arr[j]; `` arr[j] = arr[j + 1]; `` arr[j + 1] = temp; `` } `` } `` } ``}

  • 选择排序:每次从待排序区间选择最小/最大元素,放到已排序区间的末尾,效率略高于冒泡排序。

  • 插入排序:将待排序元素逐个插入到已排序区间的合适位置,类似整理扑克牌,适合数据基本有序的场景。

(2)查找算法

  • 顺序查找:从数组开头依次遍历,查找目标元素,简单但效率低(适合无序数组);

  • 二分查找 :仅适用于有序数组,通过不断将查找区间减半,快速定位目标元素,效率高(时间复杂度O(log₂n))。

4. 算法的时间复杂度与空间复杂度

用于衡量算法的效率,是算法设计的核心评估指标:

  • 时间复杂度 :描述算法执行所需的时间与输入规模的关系,常用大O表示(忽略常数、低次项和系数),比如O(1)(常数时间)、O(n)(线性时间)、O(n²)(平方时间)。

  • 空间复杂度 :描述算法执行所需的额外空间与输入规模的关系,同样用大O表示,比如冒泡排序空间复杂度为O(1)(仅用临时变量),递归算法通常空间复杂度较高。

二、异常(Java)

1. 核心定义

异常是程序运行过程中出现的意外情况(如除数为0、数组下标越界、文件找不到),会导致程序正常执行流程中断。Java中通过异常机制,捕获并处理这些意外,避免程序崩溃。

异常本质是Java中的对象,继承自Throwable类,分为两大类:Error(错误)和Exception(异常)。

2. 异常的分类(核心区分)

(1)Error(错误)

由JVM生成,程序无法处理,通常是严重的系统级错误(如内存溢出、虚拟机错误),一般不需要编写代码捕获,比如OutOfMemoryError(内存溢出)、StackOverflowError(栈溢出)。

(2)Exception(异常)

程序可以处理的异常,也是我们日常开发中重点关注的类型,分为两大类:

  • 编译时异常(受检异常):编译阶段就会报错,必须手动处理(捕获或抛出),否则无法编译,比如IOException(文件操作异常)、SQLException(数据库操作异常)。

  • 运行时异常(非受检异常):编译阶段不报错,运行时才会出现,可选择处理或不处理,比如NullPointerException(空指针异常)、ArrayIndexOutOfBoundsException(数组下标越界)、ArithmeticException(除数为0)。

3. 异常的处理方式(3种)

(1)try-catch捕获异常

核心:尝试执行可能出现异常的代码,若出现异常,捕获并处理,避免程序崩溃,格式如下:

复制代码
try {
    // 可能出现异常的代码(如除数为0)
    int a = 10 / 0;
} catch (ArithmeticException e) {
    // 捕获指定类型的异常,进行处理
    System.out.println("异常原因:" + e.getMessage()); // 输出异常信息
} finally {
    // 可选:无论是否出现异常,都会执行(常用于释放资源,如关闭文件、连接)
    System.out.println("无论是否异常,都会执行");
}

说明:可多个catch捕获不同类型异常(从子类到父类),finally可选,但若有return,finally会在return之前执行。

(2)throws抛出异常

核心:不处理异常,将异常抛给调用者,由调用者处理,格式:在方法声明后加throws 异常类型。

复制代码
// 抛出编译时异常,由调用该方法的代码处理
public static void readFile() throws IOException {
    // 可能出现IOException的代码
    FileReader fr = new FileReader("test.txt");
}

(3)throw手动抛出异常

核心:手动创建异常对象,主动抛出,用于自定义异常场景(如参数校验)。

复制代码
public static void checkAge(int age) {
    if (age < 0 || age > 120) {
        // 手动抛出运行时异常
        throw new IllegalArgumentException("年龄不合法:" + age);
    }
}

4. 自定义异常

当Java自带的异常无法满足需求时,可自定义异常,步骤:

  1. 继承Exception(编译时异常)或RuntimeException(运行时异常);

  2. 编写构造方法(默认无参、带异常信息的构造);

  3. 在需要的地方,用throw抛出自定义异常。

复制代码
// 自定义编译时异常
public class MyException extends Exception {
    // 无参构造
    public MyException() {}
    // 带异常信息的构造
    public MyException(String message) {
        super(message);
    }
}
​
// 使用自定义异常
public static void checkScore(int score) throws MyException {
    if (score < 0 || score > 100) {
        throw new MyException("分数不合法:" + score);
    }
}

5. 异常处理的注意事项

  • 捕获异常时,要避免使用catch (Exception e) 捕获所有异常(无法精准定位问题);

  • finally中避免使用return,否则会覆盖try或catch中的return值;

  • 运行时异常可不用强制处理,但编译时异常必须处理(捕获或抛出);

  • 异常处理的核心是"精准捕获、合理处理",避免程序崩溃,同时便于排查问题。

三、核心总结

  1. 算法:解决问题的步骤集合,有5大特性,重点掌握基础排序和查找算法,关注时间/空间复杂度;

  2. 异常:程序运行中的意外情况,分为Error(不可处理)和Exception(可处理),3种处理方式(try-catch、throws、throw),可自定义异常;

  3. 核心原则:算法追求高效(低时间/空间复杂度),异常追求精准处理(避免程序崩溃、便于排查)。

相关推荐
lsx2024061 小时前
SOAP Envelope 元素
开发语言
码上小翔哥1 小时前
Jackson 配置深度解析
java·后端
范范@1 小时前
day2-python基础语法
开发语言·python
qq_2518364571 小时前
基于java 私厨美食共享平台系统设计与实现(有源码)
java·开发语言·美食
杜子不疼.1 小时前
【C++ 在线五子棋对战】 - 工具类模块实现
开发语言·c++
未秃头的程序猿1 小时前
如何用 AI 写出符合规范的 Java 代码?我总结了 7 条有效建议
java·后端·ai编程
夏至春来-美美1 小时前
python 使用pytest的ini配置
开发语言·python·pytest
geovindu1 小时前
python: Mutex Pattern
开发语言·python·设计模式·互斥锁模式
永远自我1 小时前
matlab对c语言模块进行仿真
c语言·开发语言