目录
前言
函数式接口
Lambda 表达式使用实例
简单示例
1. 无参数,无返回值
2. 有参数,无返回值
3. 无参数,有返回值
4. 有参数,有返回值
解释:
集合框架
1.forEach:遍历集合
2.排序:对集合中的元素进行排序
3.映射:将集合中的每个元素转换成另一种形式
4.使用Lambda 表达式定制优先队列
实现函数式接口
1.Comparator接口
2.Consumer接口
3.Function接口
结尾
前言
Lambda 表达式 是 Java 8 引入的一项新特性,它使得 Java 编程语言更加简洁、灵活,特别是在处理函数式编程时。Lambda 表达式允许你以一种更加简洁的方式表示匿名函数(即没有名字的函数),它是 Java 对函数式编程思想的支持。 通俗地总结一下,它的作用就是让JAVA代码变得更加简洁. 本文是笔者对它的简单介绍,受制于笔者自身学识的不足,也许有不充分或者错误的地方,在此先说一声抱歉.笔者会经常审阅自己的博客,尽力确保不会有错误.
以下是它的基础语法:
基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
函数式接口
首先科普一下什么是函数式接口
@FunctionalInterface
interface Example {
void test();
}
Lambda 表达式使用实例
简单示例
1. 无参数,无返回值
如果没有参数, 括号里面也就没有值
@FunctionalInterface
interface NoArgNoReturn {
void doSomething();
}
public class Main {
public static void main(String[] args) {
// Lambda 表达式实现接口
NoArgNoReturn action = () -> System.out.println("无参数,无返回值的方法执行");
// 调用接口方法
action.doSomething();
}
}
2. 有参数,无返回值
有参数,所以括号里面要放置我们的参数
@FunctionalInterface
interface WithArgNoReturn {
void printMessage(String message);
}
public class Main {
public static void main(String[] args) {
// Lambda 表达式实现接口
WithArgNoReturn action = (message) -> System.out.println("Message: " + message);
// 调用接口方法
action.printMessage("Hello, Lambda!");
}
}
3. 无参数,有返回值
和上面的示例类似
@FunctionalInterface
interface NoArgWithReturn {
int getNumber();
}
public class Main {
public static void main(String[] args) {
// Lambda 表达式实现接口
NoArgWithReturn action = () -> 42; // 返回固定的数字
// 调用接口方法并打印返回值
System.out.println("The number is: " + action.getNumber());
}
}
4. 有参数,有返回值
(括号里面是参数 a,b), 然后我们返回 a+b的值
@FunctionalInterface
interface WithArgsWithReturn {
int sum(int a, int b);
}
public class Main {
public static void main(String[] args) {
// Lambda 表达式实现接口
WithArgsWithReturn action = (a, b) -> a + b; // 返回两个数的和
// 调用接口方法并打印返回值
System.out.println("The sum is: " + action.sum(10, 20));
}
}
这么做简化在哪里呢?请看如下例子
import java.util.*;
@FunctionalInterface
interface Example {
void test();
}
public class Main {
public static void main(String[] args) {
Example example = new Example() {
@Override
public void test() {
System.out.println("这是一个示例");
}
};
example.test();
}
}
我们这里定义了一个接口 Example
,然后在 main
方法中创建了一个匿名内部类实现了 Example
接口。这个匿名类的实现是通过 new Example() {}
来完成的。 所以对比能发现,使用Lambda确实可以简化代码.
解释:
匿名内部类(Anonymous Inner Class)是一个没有名字的类,通常在实例化时使用。它是类的一个局部实现,可以用来简化代码,尤其在只需要某个接口的一个临时实现时。
集合框架
1.forEach:遍历集合
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.forEach(item -> System.out.println(item));
2.排序:对集合中的元素进行排序
List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
numbers.sort((a, b) -> a - b); // 使用 Lambda 表达式进行升序排序
numbers.forEach(System.out::println); // 输出: 1, 2, 3, 4, 5
3.映射:将集合中的每个元素转换成另一种形式
List<String> strings = Arrays.asList("apple", "banana", "cherry");
strings.stream()
.map(String::toUpperCase) // 将字符串转为大写
.forEach(System.out::println);
4.使用Lambda 表达式定制优先队列
我们在使用PriorityQueue时,通常需要定义这是大根堆还是小根堆,我们可以使用Lambda表达式来简化这个过程
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o1-o2);
PriorityQueue<Integer> priorityQueue1 = new PriorityQueue<>(new Comparator<Integer>()
{
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
顺便提一嘴,这个操作为什么list不行呢?因为根据两者的源代码来看
PriorityQueue
实现了比较接口,它能够根据你提供的比较规则(Comparator
)来排序元素,或者通过元素自身的自然顺序(如果元素实现了 Comparable
接口)来排序。因此,它支持自动排序。
public PriorityQueue(Comparator<? super E> comparator) {
this(DEFAULT_INITIAL_CAPACITY, comparator);
}
List
不直接实现比较接口,它是一个普通的集合类,维护元素的插入顺序。要对 List
中的元素进行排序,必须显式地调用排序方法(比如 list.sort()
),并提供一个 Comparator
或让元素实现 Comparable
接口。
public interface List<E> extends Collection<E>
笔者这里也是随意的举几个例子,读者们明白意思就好.
实现函数式接口
Lambda 实现函数式接口也是它的重要功能,笔者接下来举几个例子给读者看看
1.Comparator接口
如果正常地使用该接口,应该是这样的
import java.util.*;
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ": " + age;
}
}
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
// 使用自定义 Comparator 按照年龄排序
people.sort(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age; // 按照年龄升序排序
}
});
// 输出排序后的列表
for (Person person : people) {
System.out.println(person);
}
}
}
如果使用Lambda 表达式,可以简化为
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
// 使用 Lambda 表达式按年龄排序
people.sort((o1, o2) -> o1.age - o2.age);
// 输出排序后的列表
for (Person person : people) {
System.out.println(person);
}
}
}
小科普:为什么它是函数式接口
我们透过Comparator接口的源码可以看到
boolean equals(Object obj);
他其实还有这么方法,那么这是为什么呢?
答: 这是从 Object
类继承的,不属于接口本身定义的抽象方法。
根据 Java 的定义,函数式接口的判断依据是其抽象方法的数量,而不是它是否包含其他默认方法或静态方法。
-
继承自
Object
的方法不计入抽象方法equals()
是所有类(包括接口)的通用方法,它属于Object
类,不是Comparator
定义的抽象方法。 -
默认方法和静态方法不影响函数式接口的定义
Java 8 引入默认方法和静态方法后,它们提供了更多的工具和扩展性,但这些都不影响抽象方法的唯一性。
因此,Comparator
只有一个抽象方法 compare(T o1, T o2)
,符合函数式接口的定义。
2.Consumer接口
以下是我的例子:
List<String> list1 = new ArrayList<>();
list1.add("niko");
list1.add("bit");
list1.add("ropz");
list1.add("faker");
list1.add("lwx");
list1.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
list.forEach((s -> System.out.println(s)));
3.Function接口
Function<Integer,Integer> function = x-> x *5;
System.out.println(function.apply(2));
Function<Integer,Integer> function = new Function<Integer, Integer>() {
@Override
public Integer apply(Integer integer) {
return integer*5;
}
};
System.out.println(function.apply(2));
结尾
我不敢恬不知耻地说这是一遍综合介绍Lambda 表达式的博客,因为受制于自身知识有限,我没有完整地拿出很多例子.但我可以说它初步介绍了Lambda 表达式,希望能给阅读到的小白一些总结性的思考.