我爱Java系列---【lambda表达式】
一.lambda表达式(必须掌握)
1.函数式编程思想概念
函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做
2.lambda表达式写法技巧:
只需要按照匿名内部类的形式写出代码,然后保留抽象方法的()和{},在()和{}之间添加一个->
3.lambda表达式组成
(1)一些参数
(2)一个箭头
(3)一段代码
4.lambda表达式格式:
(参数列表...)->{代码}
5.lambda表达式格式解释:
(1)(参数列表...): 和以前定义方法的参数列表(写在()中)是一致的
没有参数()留空,有多个参数,用逗号隔开
(2)->: 代表指向的动作,本质方法参数的传递
(3){}: 和以前定义方法的{}中是一样的,代表的是方法体的内容
6.Lambda表达式的省略格式
(1)数据类型可以省略: (Person p1,Person p2): 省略格式(p1,p2)
(2)()中只有一个参数,()可以省略: (Perons p): 省略格式(p) 最简化的省略格式: p
(3)->: 永远不能省略
(4){}中如果只有一条语句:
那么{},return,分号 都可以省略
但是要么全部省略,要么全部保留
7.lambda表达式的前提
(1)必须要有接口(函数式接口)
要求接口中只能有一个(必须要被覆盖重写的)抽象方法,可以有默认方法,可以有静态方法
(2)必须要有接口作为方法的参数
@Override: 检测是否是对父类方法的覆盖重写
@FunctionalInterface: 检测是否是函数式接口
二.常用的函数是接口
1.消费型接口
java.util.function.Consumer<T>: 消费型接口
抽象方法: 必须掌握
public abstract void accept(T t): 消费一个指定泛型T类型的数据
注意:
什么叫做消费呢?
因为accept方法是抽象的,只要做覆盖重写{}后,就叫消费了,至于{}中写了哪些代码,我不管
2.判断型接口
java.util.function.Predicate<T>: 判断型接口
抽象方法: 必须掌握
public abstract boolean test(T t): 根据T类型的参数t,返回一个boolean类型的结果
三.Stream流
1.获取Stream流对象的方法(两种)
(1)Collection<T>集合
默认方法:必须由Collection接口的实现类(ArrayList/LinkedList/HashSet/LinkedHashSet)对象调用
Stream<T> stream() :获取Collection集合对象的Stream流对象
代码演示:
//获取List集合的Stream对象
List<String> list = new ArrayList<>();
Stream<String> s1 = list.stream();
System.out.println(s1);
//获取Set集合的Stream对象
Set<Integer> set = new HashSet<>();
Stream<Integer> s2 = set.stream();
System.out.println(s2);
Map<String,String> map = new HashMap<>();
//Map键的Set集合
Set<String> set2 = map.keySet();
Stream<String> s3 = set2.stream();
System.out.println(s3);
//Map值的Collection集合
Collection<String> coll = map.values();
Stream<String> s4 = coll.stream();
System.out.println(s4);
//Map键值对的Set集合
Set<Map.Entry<String, String>> set3 = map.entrySet();
Stream<Map.Entry<String, String>> s5 = set3.stream();
System.out.println(s5);
System.out.println("----------");
String[] arr = {"Hello","World","java"};
Stream<String> s6 = Stream.of(arr);
System.out.println(s6);
Stream<String> s7 = Stream.of("Hello", "World", "java");
System.out.println(s7);
}
}
(2)Stream接口的静态方法静态方法
java.util.stream.Stream<T> 接口:
public static <T> Stream<T> of(T ... t): 把方法的可变参数指定的具体数据,转换成Stream流对象
参数:
T ... t: 可变参数 可以传递数组,参数列表,也可以不传递
Stream<String> s = Stream.of("大娃", "二娃", "娃"}
2.Stream流中的forEach方法
void forEach(Consumer<T> action): 终结方法,调用此方法后,Stream流对象将不可以继续使用
该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理,不保证顺序
Consumer接口:
抽象方法:
void accept(T t)
s->sout(s);System.out::println
3.Stream流中的count方法
long count() : 终结方法,调用此方法后,Stream流对象将不可以继续使用
返回Stream流对象中的元素的个数,但是返回值类型是long
4.Stream流中的filter方法
Stream<T> filter(Predicate<T> predicate) :
按照方法参数predicate对Stream流对象中的元素进行过滤,并返回新的Stream流对象
Predicate<T>接口:
抽象方法:
boolean test(T t)
5.Stream流中的limit方法和skip方法
Stream<T> limit(long n): 获取流对象中的前n个元素,返回新的Stream流对象
Stream<T> skip(long n): 跳过流对象中的前n个元素,返回新的Stream流对象
6.Stream流中的静态concat方法
static <T> Stream<T> concat(Stream<T> a, Stream<T> b):
把两个流对象a和b合并成一个流对象,并返回
四、综合案例
/* Stream综合案例 1. 第一个队伍只要名字为3个字的成员姓名; 2. 第一个队伍筛选之后只要前3个人; 3. 第二个队伍只要姓张的成员姓名; 4. 第二个队伍筛选之后不要前2个人; 5. 将两个队伍合并为一个队伍; 6. 打印整个队伍的姓名信息。 按照Stream流+匿名内部类的形式 */ public class Demo02ListEach { public static void main(String[] args) { List<String> o = new ArrayList<>(); o.add("迪丽热巴"); o.add("宋远桥"); o.add("苏星河"); o.add("老子"); o.add("庄子"); o.add("孙子"); o.add("洪七公"); //获取第一个队伍的流对象 Stream<String> os1 = o.stream(); //1. 第一个队伍只要名字为3个字的成员姓名; Stream<String> os2 = os1.filter(new Predicate<String>() { @Override public boolean test(String s) { return s.length() == 3; } }); //2. 第一个队伍筛选之后只要前3个人; Stream<String> os3 = os2.limit(3); List<String> t = new ArrayList<>(); t.add("古力娜扎"); t.add("张无忌"); t.add("张三丰"); t.add("赵丽颖"); t.add("张二狗"); t.add("张天爱"); t.add("张三"); //获取第二个队伍的流对象 Stream<String> ts1 = t.stream(); //3. 第二个队伍只要姓张的成员姓名; Stream<String> ts2 = ts1.filter(new Predicate<String>() { @Override public boolean test(String s) { return s.startsWith("张"); } }); //4. 第二个队伍筛选之后不要前2个人; Stream<String> ts3 = ts2.skip(2); //5. 将两个队伍合并为一个队伍; Stream<String> ots = Stream.concat(os3, ts3); //6. 打印整个队伍的姓名信息 ots.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }); } } |
/* |
/* Stream综合案例 1. 第一个队伍只要名字为3个字的成员姓名; 2. 第一个队伍筛选之后只要前3个人; 3. 第二个队伍只要姓张的成员姓名; 4. 第二个队伍筛选之后不要前2个人; 5. 将两个队伍合并为一个队伍; 6. 打印整个队伍的姓名信息。 按照Stream流+lambda标准格式的形式(分1步完成) */ public class Demo05ListEach { public static void main(String[] args) { List<String> o = new ArrayList<>(); o.add("迪丽热巴"); o.add("宋远桥"); o.add("苏星河"); o.add("老子"); o.add("庄子"); o.add("孙子"); o.add("洪七公"); List<String> t = new ArrayList<>(); t.add("古力娜扎"); t.add("张无忌"); t.add("张三丰"); t.add("赵丽颖"); t.add("张二狗"); t.add("张天爱"); t.add("张三"); //获取第一个队伍的流对象 //1. 第一个队伍只要名字为3个字的成员姓名; //2. 第一个队伍筛选之后只要前3个人; //获取第二个队伍的流对象 //3. 第二个队伍只要姓张的成员姓名; // 4. 第二个队伍筛选之后不要前2个人; //5. 将两个队伍合并为一个队伍; //6. 打印整个队伍的姓名信息 Stream.concat( o.stream().filter(name->name.length()==3).limit(3), t.stream().filter(name->name.startsWith("张")).skip(2) ).forEach(name-> System.out.println(name)); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?