
Java基础-Lambda&Stream
2026/7/1
lambda表达式
简介:
lambda表达式是jdk8的新特性,取代了匿名内部类:
new Thead( new Runnable(){
public void run(){
}
}).start();
更加优雅,尤其在集合的遍历和其他集合操作中,能够优化代码结构。JDK也提供内置的函数式接口供我们使用。
使用场景
Lambda规定 接口中只有一个需要被实现的方法时,才可使用Lambda表达式
例如Runnable接口,只有一个run方法需要被重写
注意:是只有一个需要被实现的方法,不是规定接口中只能有一个方法
jdk8中有一个新特性, default 被其修饰的方法会有默认实现,不是必须被实现的方法,不影响lambda的使用。
@FunctionInterface 验证当前接口是否满足lambda表达式的规定,一般和lambda表达式一起出现,即:接口中只能有一个需要被实现的方法
java
package com.kaguya.demo;
/**
* lambda表达式 学习
* @author : kaguya
* @date : 13:00 2021/6/15
*/
//验证当前接口是否满足lambda表达式的规定,一般和lambda表达式一起出现,即:接口中只能有一个需要被实现的方法
@FunctionalInterface //函数式接口注解
public interface MyInterface {
//唯一需要被实现的接口
void Say();
//default关键字,代表其有默认实现,可以不必实现。
default void Shout(){
}
}
lambda表达式写法
1.准备工作 定义不同返回值不同参数的接口
java
package com.kaguya.lambda;
/**
* lambda 接口 测试类
* @author : kaguya
* @date : 13:08 2021/6/15
*/
public class LambdaInterface {
//无返回值 无参数
@FunctionalInterface
public interface NoReturnNoParam {
void method();
}
//无返回值 一个参数
@FunctionalInterface
public interface NoReturnOneParam {
void method(int i);
}
//无返回值 多个参数
@FunctionalInterface
public interface NoReturnManyParam {
void method(int i,int j);
}
//有返回值 无参数
@FunctionalInterface
public interface HasReturnNoParam {
int method();
}
//有返回值 一个参数
@FunctionalInterface
public interface HasReturnOneParam {
int method(int i);
}
//有返回值 多个参数
@FunctionalInterface
public interface HasReturnManyParam {
int method(int i,int j);
}
}
写法:
接口声明 变量名 = () ->{};
其中。()内放参数,->箭头函数指向,{}方法体
java
package com.kaguya.demo;
import com.kaguya.lambda.LambdaInterface;
/**
* demo测试
* 总结:(参数) ->{方法体,返回值};
* {}中只有一行代码可以省略
* @author : kaguya
* @date : 13:10 2021/6/15
*/
public class Test {
public static void main(String[] args) {
//lambda写法测试
//无参数 无返回值
//普通写法 匿名内部类的形式
LambdaInterface.NoReturnNoParam in0 = new LambdaInterface.NoReturnNoParam() {
@Override
public void method() {
System.out.println("ok");
}
};
//lambda写法
LambdaInterface.NoReturnNoParam in1 = () -> {
System.out.println("ok");
};
//调用
in1.method();
//一个参数 无返回值
LambdaInterface.NoReturnOneParam in2 = (i) ->{
System.out.println("ok"+i);
};
//调用
in2.method(3);
//多个参数 无返回值
LambdaInterface.NoReturnManyParam in3 = (i,j) ->{
System.out.println("ok"+i+"ok"+j);
};
//调用
in3.method(3,4);
//无参 有返回值
LambdaInterface.HasReturnNoParam in4 = () -> {
return 0;
};
//一参 有返回值
LambdaInterface.HasReturnOneParam in5 = (i) -> {
return i;
};
//多参 有返回值
LambdaInterface.HasReturnManyParam in6 = (i,j) ->{
return i+j;
};
}
}
简化语法
- 简化参数类型,在()中可以省略参数类型,但是必须省略所有
- 简化参数小括号,如果只有一个参数,可以省略小括号()
- 简化方法体大括号,如果方法体中只有一行代码可以省略掉大括号{}
- 如果方法体只有一行且为return语句 可以省略大括号以及return 关键字
java
package com.kaguya.demo;
import com.kaguya.lambda.LambdaInterface;
/**
* Lambda 语法 简化
* @author : kaguya
* @date : 13:23 2021/6/15
*/
public class Test2 {
public static void main(String[] args) {
//1.简化参数类型,在()中可以省略参数类型,但是必须省略所有
LambdaInterface.NoReturnManyParam in1 = (i,j) -> {
};
//2.简化参数小括号,如果只有一个参数,可以省略小括号()
LambdaInterface.NoReturnOneParam in2 = i -> {};
//3.简化方法体大括号,如果方法体中只有一行代码可以省略掉大括号{}
LambdaInterface.NoReturnNoParam in3 = () -> System.out.println("hello");
//4.如果方法体只有一行且为return语句 可以省略大括号以及return 关键字
LambdaInterface.HasReturnManyParam in4 = (i,j) ->i+j;
}
}
有时我们已经对接口进行了实现,那么我们该如何引用呢?
只支持方法
类名(或者对象名) :: 方法名
java
package com.kaguya.demo;
import com.kaguya.lambda.LambdaInterface;
/**
* lambda 语法 引用
* @author : kaguya
* @date : 17:17 2021/6/15
*/
public class Test3 {
public static void main(String[] args) {
//引用其他已经定义好的接口实现,此处为静态方法 所以 可以 类名::方法名
LambdaInterface.HasReturnNoParam hp = Test3::sum;
hp.method();
//成员方法
Test3 test3 = new Test3();
LambdaInterface.HasReturnNoParam hp2 = test3::sum2;
hp2.method();
}
//当前类的静态方法
public static int sum(){
System.out.println("sum");
return 0;
}
//当前类的成员方法
public int sum2(){
System.out.println("sum2");
return 1;
}
}
注意,平常的对象能调用静态方法,lambda调用方法时,无法使用对象调用静态方法
lambda 引用 构造方法 (new)
与引用方法的写法差不多,具体为(xxx) -> new Item(xxx); 简写为 Item::new
java
package com.kaguya.demo;
/**
* lambda 构造方法的引用
* @author : kaguya
* @date : 17:29 2021/6/15
*/
//接口 返回Item
interface BlankConstruction {
Item getItem();
}
interface ParamConstruction {
Item getItem(String name,Integer age);
}
//实体类
class Item {
private String name;
private Integer age;
public Item() {
}
public Item(String name, Integer age) {
this.name = name;
this.age = age;
}
}
//main
public class Test4 {
public static void main(String[] args) {
//new 构造方法 引用构造方法
//调用构造方法
BlankConstruction bc1 = () -> new Item();
//调用无参构造方法
bc1.getItem();
//简化写法
BlankConstruction bc2 = Item::new;
bc2.getItem();
//调用有参
ParamConstruction pc1 = (name, age) -> new Item(name, age);
pc1.getItem("hello",3);
//简化写法
//调用有参
ParamConstruction pc2 = Item::new;
pc2.getItem("hello",3);
}
}
lambda 创建线程
java
package com.kaguya.demo;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* lambda 创建线程
* @author : kaguya
* @date : 17:48 2021/6/15
*/
public class Test5 {
public static void main(String[] args) {
//runnable
//对比 传统创建Thread 需要实现Runnable接口的run方法
new Thread(
new Runnable() {
@Override
public void run() {
System.out.println("run");
}
}
).start();
//lambda
new Thread( () -> {
System.out.println("run run run");
}).start();
//callable
ExecutorService executorService = Executors.newCachedThreadPool();
//executorService的submit方法有多个,submit 无参 lambda 默认匹配 Runnable;有返回值自动匹配 Callable
executorService.submit( () -> {
System.out.println("我是runnable的接口实现");
});
executorService.submit( () -> {
System.out.println("我是callable的接口实现");
});
}
}
lambda遍历集合
java
package com.kaguya.demo;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;
/**
* lambda遍历集合
* @author : kaguya
* @date : 22:27 2021/6/15
*/
public class Test6 {
public static void main(String[] args) {
//集合遍历
List<Integer> list = Arrays.asList(1, 9, 7, 4, 14, 2, 5, 97);
//传统
for(Integer l : list){
System.out.println(l);
}
//lambda forEach里面就是增强for循环
list.forEach(item ->{
System.out.println(item);
});
//直接打印
list.forEach(System.out::print);
//删除集合中的元素 参数 返回值写上 条件 好像只能用对象
//list.removeIf(item -> item == 9);
//排序 传统的排序是需要实现Comparator(比较器) 中的compare方法
//Comparator<T> 通过compare方法对两个数据进行比较最终进行排序
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
//lambda
Collections.sort(list,(o1, o2) -> {
return o1-o2;
});
System.out.println(list);
}
}
Stream流
一、概述
Stream 是 JDK8 配合 Lambda 推出的集合流式处理 API,用来简化集合遍历、筛选、转换、聚合等操作。
- 核心特点:流式链式调用,分为 中间操作、终端操作
- 不修改原集合:所有操作都会生成新结果,原集合数据不变
- 惰性求值:中间操作仅做记录,只有执行终端操作才会真正执行计算
- 支持串行流、并行流(
parallelStream()),自动利用多线程
二、Stream 获取方式
- 集合直接调用
stream()/parallelStream()(最常用) - 数组通过
Arrays.stream(数组) - Stream.of (T... values) 创建单列流
java
List<Integer> list = Arrays.asList(1,2,3,4,5);
// 1.集合获取串行流
Stream<Integer> stream = list.stream();
// 并行流
Stream<Integer> parallelStream = list.parallelStream();
// 2.数组转流
Integer[] arr = {10,20,30};
Stream<Integer> arrStream = Arrays.stream(arr);
// 3.直接创建流
Stream<String> strStream = Stream.of("a","b","c");
三、流两类操作区分
-
中间操作:返回新 Stream,可链式拼接,惰性执行
filter、map、flatMap、sorted、distinct、limit、skip
-
终端操作:关闭流,触发计算,返回非 Stream 结果,一个流只能调用一次终端操作
forEach、collect、count、max、min、anyMatch、allMatch、findFirst
四、常用中间操作示例
java
List<Integer> list = Arrays.asList(1, 9, 7, 4, 14, 2, 5, 97);
// 1.filter 过滤,保留满足条件元素
List<Integer> filterList = list.stream()
.filter(item -> item > 5)
.collect(Collectors.toList());
// 2.map 转换映射:统一修改元素类型/值
List<String> mapList = list.stream()
.map(item -> "数字:" + item)
.collect(Collectors.toList());
// 3.distinct 去重
List<Integer> distinctList = list.stream()
.distinct()
.collect(Collectors.toList());
// 4.sorted 排序
// 自然升序
List<Integer> sortAsc = list.stream().sorted().collect(Collectors.toList());
// 自定义降序
List<Integer> sortDesc = list.stream().sorted((o1,o2)->o2-o1).collect(Collectors.toList());
// 5.limit 截取前N个元素
List<Integer> limitList = list.stream().limit(3).collect(Collectors.toList());
// 6.skip 跳过前N个元素
List<Integer> skipList = list.stream().skip(2).collect(Collectors.toList());
五、flatMap 扁平化流(处理嵌套集合)
场景:集合内包含子集合,需要把多层数据拆成单层
java
List<List<String>> nestedList = Arrays.asList(
Arrays.asList("a","b"),
Arrays.asList("c","d")
);
// flatMap 将子集合转为流,合并为单层流
List<String> flatList = nestedList.stream()
.flatMap(subList -> subList.stream())
.collect(Collectors.toList());
// 输出 [a,b,c,d]
六、常用终端操作
java
List<Integer> list = Arrays.asList(1, 9, 7, 4, 14, 2, 5, 97);
// 1.forEach 遍历输出(Lambda)
list.stream().forEach(item -> System.out.println(item));
list.stream().forEach(System.out::println);
// 2.collect 收集为集合(最核心)
// 转List
List<Integer> newList = list.stream().collect(Collectors.toList());
// 转Set(自动去重)
Set<Integer> set = list.stream().collect(Collectors.toSet());
// 转Map(key:元素,value:元素*2)
Map<Integer, Integer> map = list.stream()
.collect(Collectors.toMap(k->k, v->v*2));
// 3.count 统计元素个数
long count = list.stream().count();
// 4.max/min 最大最小值
Optional<Integer> max = list.stream().max(Integer::compareTo);
Optional<Integer> min = list.stream().min((o1,o2)->o1-o2);
// 5.匹配操作
boolean anyMatch = list.stream().anyMatch(item -> item > 50); //任意一个满足
boolean allMatch = list.stream().allMatch(item -> item > 0); //全部满足
boolean noneMatch = list.stream().noneMatch(item -> item < 0); //全部不满足
// 6.findFirst 获取第一个元素
Optional<Integer> first = list.stream().findFirst();
first.ifPresent(val -> System.out.println("首个值:"+val));
七、Collectors 高级收集器(分组、求和、拼接)
java
List<Item> itemList = Arrays.asList(
new Item("苹果",10),
new Item("香蕉",5),
new Item("苹果",15)
);
// 1.groupingBy 分组:按name分组
Map<String, List<Item>> groupMap = itemList.stream()
.collect(Collectors.groupingBy(Item::getName));
// 2.summingInt 求和
int totalAge = itemList.stream()
.collect(Collectors.summingInt(Item::getAge));
// 3.joining 字符串拼接
String nameStr = itemList.stream()
.map(Item::getName)
.collect(Collectors.joining("、"));
八、并行流 parallelStream
java
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
// 并行流计算
list.parallelStream()
.filter(i -> i % 2 == 0)
.forEach(System.out::println);
注意:并行流操作内不要修改外部共享变量,存在线程安全问题。
九、Optional 配合 Stream(空指针防护)
Stream 返回 findFirst、max/min 都会包装 Optional,避免空指针
java
List<Integer> list = new ArrayList<>();
Optional<Integer> opt = list.stream().findFirst();
// 存在则执行,不存在不报错
opt.ifPresent(num -> System.out.println(num));
// 为空给默认值
Integer res = opt.orElse(0);
十、Lambda + Stream 综合完整案例
java
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 9, 7, 4, 14, 2, 5, 97);
// 需求:过滤大于5 → 全部*2 → 降序排序 → 转List
List<Integer> result = list.stream()
.filter(item -> item > 5)
.map(item -> item * 2)
.sorted((o1,o2)->o2-o1)
.collect(Collectors.toList());
System.out.println(result);
}
}
— END —