点击上方“猿芯”,选择“设为星标

后台回复"1024",有份惊喜送给面试的你

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

1.1 语法组成

  1. 操作符为" -> " ,被称为 Lambda 操作符或箭头操作符;

  2. 将 Lambda 分为两个部分:

    1. 左侧:指定了 Lambda 表达式需要的参数列表

    2. 右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即Lambda 表达式要执行的功能。

1.2 基本用法

1.2.1 未使用和使用Lambda表达式的区别

@Slf4j
public class TestLambda {//未使用和使用lambda表达式,对比static void testRunLambdaContrast(){// 不使用lambda表达式,创建一个线程Runnable runnable1 = new Runnable() {@Overridepublic void run() {log.info("------ 不使用lambda表达式,创建一个线程 ------");}};// 启动线程new Thread(runnable1).start();// 使用lambda表达式,创建一个线程Runnable runnable2 = () -> log.info("------ 使用lambda表达式,创建一个线程 ------");// 启动线程2new Thread(runnable2).start();}public static void main(String[] args) {//测试 未使用和使用lambda表达式,对比testRunLambdaContrast();}}

总结:未使用和使用Lambda表达式都可以实现抽象方法,但是使用Lambda方法后会更加简洁;

1.2.2 带一个参数没有返回值

1.2.2.1 带一个参数没有返回值 标准写法
// 借助java8中 消费型函数式接口,讲解基本用法
// 不使用lambda表达式实现
Consumer<String> consumer1 = new Consumer<String>() {@Overridepublic void accept(String s) {log.info("------ 不使用lambda表达式,实现Consumer1接口,消费数据:{} ------",s);}
};// 使用消费型接口1
consumer1.accept("kh96正在学习lambda表达式,标准写法");// 使用lambda表达式,用法:带 1 个参数,没有返回值,标准写法
Consumer<String> consumer2 = (String s) -> {log.info("------ 使用lambda表达式,实现Consumer2接口,消费数据:{} ------",s);
};// 使用消费型接口2
consumer2.accept("kh96正在学习lambda表达式,标准写法");
1.2.2.2 简化写法:一个参数,可以省略类型声明
//一个参数,可以省略类型声明
Consumer<String> consumer3 = (s) -> {log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);
};consumer3.accept("kh96正在学习lambda表达式,一个参数,可以省略类型声明");
1.2.2.3 简化写法:一个参数,可以省略小括号(没有参数,多个参数不能省略)
//一个参数,可以省略小括号(没有参数,多个参数不能省略)
Consumer<String> consumer4 = s -> {log.info("------ 使用lambda表达式,实现Consumer4接口,消费数据:{} ------",s);
};consumer4.accept("kh96正在学习lambda表达式,一个参数,可以省略小括号");
1.2.2.4 简化写法:实现只有一条语句,可以省略大括号(有多条语句,不可以省略)
//实现只有一条语句,可以省略大括号(有多条语句,不可以省略)
Consumer<String> consumer5 = s -> log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);consumer5.accept("kh96正在学习lambda表达式,实现只有一条语句,可以省略大括号");
1.2.2.5 简化写法:实现有多条语句,不可以省略大括号
//实现有多条语句,不可以省略大括号
Consumer<String> consumer6 = s -> {log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);
};consumer6.accept("kh96正在学习lambda表达式,实现有多条语句,不可以省略大括号");

1.2.3 带多个参数,有返回值

1.2.3.1 未使用 lambda 表达式,用法:带多个参数,有返回值
// 借助Comparator接口,讲解多个参数
Comparator<Integer> comparator1 = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1.compareTo(o2);}
};// 未使用lambda表达式,用法:带多个参数,有返回值
log.info("------ 不使用lambda表达式,实现Comparator接口,比较12,23的大小:{} ------",comparator1.compare(12,23));// 小于 -1,大于 1,等于 0
1.2.3.2 简化写法:省略参数类型,但是不可以省略小括号,一条语句省略大括号,跟返回值无关(不用手动加return)
//省略参数类型,但是不可以省略小括号,一条语句省略大括号,跟返回值无关(不用手动加return)
Comparator<Integer> comparator2 = (o1,o2) -> o1.compareTo(o2);log.info("------ 使用lambda表达式,实现Comparator接口,比较23,12的大小:{} ------",comparator2.compare(23,12));// 大于 1
1.2.3.3 简化写法:多条语句不可以省略大括号,带返回值(需手动加return)
//多条语句不可以省略大括号,带返回值(需手动加return)
Comparator<Integer> comparator3 = (o1,o2) -> {log.info("------ 比较原数值为:{},{}",o1,o2);return o1.compareTo(o2);
};
log.info("------ 使用lambda表达式,实现Comparator接口,比较22,22的大小:{} ------",comparator3.compare(22,22));// 等于 0

1.3 java8中提供的函数式接口

1.3.1 消费型接口 Consumer (方法有一个参数,没有返回值)

1.3.1.1 自定义方法 (使用接口的 void accept(T t) )
//自定义方法,带有一个消费型接口参数,可以实现一个方法,处理不同的业务场景
static void useConsumer(Double salary,Consumer<Double> consumerDate){consumerDate.accept(salary);
}
1.3.1.2 方法调用
static void testLambdaConsumer(){//场景,同一个接口,有多个实现,以前,必须要创建接口的多个实现类,现在使用lambda,把接口的实现交给调用方法传递//实现1:Tom发了5000工资,去买手机,模拟接口的第一个实现//以前,必须提供接口的实现类对象useConsumer(5000.0,salary -> log.info("Tom,工资:{},5000买手机",salary));//实现1:Tom发了10000工资,去买手机,买平板,模拟接口的第二个实现//以前,必须提供接口的 两个 实现类对象useConsumer(10000.0,slary -> {log.info("JiMe工资:{},5000买手机",slary);log.info("JiMe工资:{},4000买平板",slary);});}
1.3.1.3 测试结果

1.3.2 供给型接口 Supplier(方法没有参数,可以返回任意类型的结果)

1.3.2.1 自定义方法 (使用接口的 T get() )
//带一个供给型参数,可以实现同一个方法,处理实现同一个方法,处理不同的业务场景,给的数据不同,返回的结果不同
static String useSupplier(Double salary, Supplier<Double> supplierData){//判断是否高薪的逻辑if(salary > supplierData.get()){return "高薪";}return "底薪";
}
1.3.2.2 方法调用
static void testLambdaSupplier(){//场景:不同的部门,针对高薪的判断条件不同,比如:学术部高于8000算高薪,教职部门高于5000算高薪//以前的写法:根据不同的不同,增加if...else 判断,随着部门的增加,你分的判断会越来越复杂log.info("--- 学术部:工资:{},是否高薪:{} ---",9000.0,useSupplier(9000.0,() -> 8000.0));log.info("--- 学术部:工资:{},是否高薪:{} ---",7000.0,useSupplier(7000.0,() -> 8000.0));log.info("--- 教职部:工资:{},是否高薪:{} ---",7000.0,useSupplier(7000.0,() -> 5000.0));log.info("--- 教职部:工资:{},是否高薪:{} ---",4000.0,useSupplier(7000.0,() -> 5000.0));}
1.3.2.3 测试结果

1.3.3 断言型接口 Predicate(方法有一个参数,有返回值-布尔类型)

1.3.3.1 自定义方法 (使用接口的 boolean test(T t) )
//将判断条件交给调用方法
static List<String> userPredicate(List<String> nameList, Predicate<String> predicateData){//定义要返回的姓名集合List<String> returnNameList = new ArrayList();//使用断言型接口,根据传过来的实现,返回不同的结果nameList.forEach(name ->{//调用断言型接口的test方法,进行挑选数据if(predicateData.test(name)){returnNameList.add(name);}});//返回符合条件的集合数据return  returnNameList;}
1.3.3.2 方法调用
static void testLambdaPredicate(){//使用场景//已知姓名集合,根据不同的场景,筛选不同的姓名结果List<String> nameList = Arrays.asList("Lilei","Hanmeinei","lisi","zhangsan","xiaolong","xiaohu");//获取姓名集合中所有包含n的姓名集合,可以定义第一个方法,实现//获取集合中包含i 或者a的姓名集合,可以定义第二个方法,实现//随着规则的改变,实现的方法越来越多,去简化,所有的方法就是判断规则不同,其他都一样,可以使用断言型接口,优化//获取姓名集合中所有包含n的姓名集合List<String> nameList_n = userPredicate(nameList,name -> name.contains("n"));log.info("姓名集合中所有包含n的姓名集合:{}",nameList_n);//获取集合中包含i 或者a的姓名集合List<String> nameList_i_a = userPredicate(nameList,name -> name.contains("i") || name.contains("a"));log.info("获取集合中包含i 或者a的姓名集合:{}",nameList_i_a);}
1.3.3.3 测试结果

1.3.4 函数接口 Function,有任意类型参数,有任意类型返回值

1.3.4.1 自定义方法(使用接口的R apply(T t) ) 和 方法调用
static void testLambdaFunction(){Function<Integer,Double> function = num -> new Random().nextInt(num)*1.0;log.info("--- 使用函数型接口,接收整数:{},返回随机浮点型结果:{} ---",96,function.apply(96));}
1.3.4.2 测试结果

1.3.5 自定义函数式接口

// 自定义的函数式接口:带一个任意类型参数,返回String类型值
// 定义:凡是一个接口中,只有一个抽象方法,那这个接口就是函数式接口,可以别注解 //@FunctionalInterface修饰
@FunctionalInterface
public interface MyFunctionInterface<T> {//函数式接口中的唯一抽象方法String helloKh96(T t);//可以增加默认方法,允许的default void hiKH96(){//默认方法}}

2、StreamAPI

2.1 创建流 有限流 和 无限流

2.1.1 有限流

//有限流, 输出1,3,5,7,9 的平方
log.info("\n----- 输出1,3,5,7,9 的平方 -----");
Stream.of(1,3,5,7,9).forEach(num -> System.out.print(num * num + ";"));

测试结果:

2.1.2 无线流

2.1.2.1 iterate
//无限流:输出前18个奇数
log.info("\n ----- 输出前18个奇数 ------");
Stream.iterate(1,n -> n+2).limit(10).forEach(num -> System.out.print(num + ";"));
2.1.2.2 generate
//无限流:输出10个随机数
log.info("\n ----- 输出前18个随机数 ------");
Stream.generate(() -> new Random().nextInt(100)).limit(10).forEach(num -> System.out.print(num+";"));

测试结果:

2.2 创建流 基于数组 和 集合

2.2.1 基于数组

//基于数组
int[] nums = {66,99,44,11,22,55,77,88};//通过Arrays工具类提供的stream 方法
int min = Arrays.stream(nums).min().getAsInt();
int max = Arrays.stream(nums).max().getAsInt();
log.info("\n ------ 数组最小值为 :{} --------",min);
log.info("\n ------ 数组最大值为 :{} --------",max);

测试结果:

2.2.2 基于集合

//基于集合
List<String> nameList = Arrays.asList("Lilei","Hanmeinei","lisi","zhangsan","xiaolong","xiaohu");//通过集合对象的stream方法
nameList.stream().map(name -> name.toLowerCase()).forEach(System.out::println);

测试结果:

2.3 流的中间操作

2.3.1 筛选和切片

2.3.1.0 数据准备
2.3.1.0.1 bean
//小说实体
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Story {// 编号private Integer id;// 书名private String name;// 作者private String author;// 价格private Double price;// 章节private Integer sections;// 分类private String category;}
2.3.1.0.2 StoryUtil
//小说工具类
public class StoryUtil {public static List<Story> stories = new ArrayList<>();static {stories.add(Story.builder().id(101).name("斗破苍穹").author("zhangsan").price(109.9).sections(1202).category("玄幻").build());stories.add(Story.builder().id(201).name("斗罗大陆").author("lisi").price(88.9).sections(999).category("科幻").build());stories.add(Story.builder().id(301).name("凡人修仙传").author("wangwu").price(77.9).sections(1303).category("武侠").build());stories.add(Story.builder().id(401).name("圣墟").author("zhuliu").price(121.9).sections(1404).category("玄幻").build());stories.add(Story.builder().id(501).name("吞噬星空").author("sunqi").price(135.9).sections(996).category("历史").build());stories.add(Story.builder().id(601).name("完美世界").author("zhaoba").price(66.9).sections(999).category("玄幻").build());stories.add(Story.builder().id(701).name("大王饶命").author("qianjiu").price(135.9).sections(997).category("玄幻").build());stories.add(Story.builder().id(801).name("大奉打更人").author("zhoushi").price(133.9).sections(1606).category("军事").build());}
}
2.3.1.1 筛选:filter
//筛选: filter,相当于数据库中的where条件
log.info("-------------- 筛选: filter ----------------");
//查看小说集合中,价格大于100块的所有小说
StoryUtil.stories.stream().filter(story -> story.getPrice() > 100).forEach(System.out::println);//练习:查看小说集合中,所有章节数大于1000且作者中包含n的小说
log.info("\n------- 查看小说集合中,所有章节数大于1000且作者中包含n的小说 ---------");
StoryUtil.stories.stream().filter(story -> story.getSections() > 1000 && story.getAuthor().contains("n") ).forEach(System.out::println);

测试结果1:

测试结果2:

2.3.1.2 截断:limit
//截断: limit 相当于数据库的limit条数
log.info("\n---------- 截断: limit ---------");
//查询小说集合,所有价格大于100的前三本
StoryUtil.stories.stream().filter(story -> story.getPrice() >100).limit(3).forEach(System.out::println);

测试结果:

2.3.1.3 跳过:skip
//跳过:skip,相当于数据库跳过数据条数
log.info("\n------------- 跳过:skip-----------------");
//查询小说集合,所有价格大于100的前三本,后的所有小说
log.info("\n------------- 查询小说集合,所有价格大于100的前三本,后的所有小说-----------------");
StoryUtil.stories.stream().filter(story -> story.getPrice() >100).skip(3).forEach(System.out::println);

测试结果:

2.3.1.4 去重:distinct
//去重:distinct,相当于数据库中的去重,了解
log.info("\n------------- 去重:distinct,相当于数据库中的去重 -----------------");
Stream.of(22,33,55,11,66,33,55,11,55).distinct().forEach(System.out::println);

测试结果:

2.3.2 映射和排序

2.3.2.1 映射:map
//已知姓名集合
List<String> nameList = Arrays.asList("Lilei","Hanmeinei","lisi","zhangsan","xiaolong","xiaohu");//映射:map,可以将流中发的元素进行转换或这提取,会自动指定的规则作用到所有的元素上,并返回一个新的流
log.info("-------------- 映射: map ----------------");//将姓名集合中,所有包含i的姓名,转换为大写并输出
//nameList.stream().filter(name -> name.contains("i")).map(name -> name.toUpperCase()).forEach(System.out::println);
nameList.stream().filter(name -> name.contains("i")).map(String::toUpperCase).forEach(System.out::println);

测试结果:

2.3.2.2 映射:map 输出单个属性
//将小说集合中,章节小于1000的作者转换为大写,输出作者
log.info("\n-------------- 将小说集合中,章节小于1000的作者转换为大写,输出作者 --------------");
//StoryUtil.stories.stream().filter(story -> story.getSections() < 1000).map(story -> story.getAuthor()).map(string -> string.toUpperCase()).forEach(System.out::println);
StoryUtil.stories.stream().filter(story -> story.getSections() < 1000).map(Story::getAuthor).map(string -> string.toUpperCase()).forEach(System.out::println);

测试结果:

2.3.2.3 映射: mapToInt
//获取所有小说的书名长度
log.info("\n-------------- 获取所有小说的书名长度 --------------");
// StoryUtil.stories.stream().map(story -> story.getName().length()).forEach(System.out::println);
StoryUtil.stories.stream().mapToInt(story -> story.getName().length()).forEach(System.out::println);

测试结果:

2.3.2.4 消费:peek
//消费:peek,  将小说价格增加50元后,价格大于130的
log.info("\n-------------- 消费:peek,  将小说价格增加50元后,价格大于130的 --------------");
StoryUtil.stories.stream().peek(story -> story.setPrice(story.getPrice()+50)).filter(story -> story.getPrice()>130).forEach(System.out::println);

测试结果:

2.3.2.5 排序:sorted
//排序:sorted ,给姓名排序
log.info("\n -------------- 排序:sorted ,给姓名排序 --------------");
nameList.stream().sorted().forEach(System.out::println);

2.3.2.6 自定义排序规则
//自定义排序,先按照价格排序,价格相同,按照章节排序
log.info("\n--------- 自定义排序,先按照价格排序,价格相同,按照章节排序 ---------");
StoryUtil.stories.stream().sorted((s1,s2)->{int sortPrice = Double.compare(s1.getPrice(),s2.getPrice());if(sortPrice == 0){return Double.compare(s1.getSections(),s2.getSections());}return sortPrice;}).forEach(System.out::println);

测试结果:

往期推荐

  1. 肝九千字长文 | MyBatis-Plus 码之重器 lambda 表达式使用指南,开发效率瞬间提升80%

  2. 用 MHA 做 MySQL 读写分离,频繁爆发线上生产事故后,泪奔分享 Druid 连接池参数优化实战

  3. 微服务架构下,解决数据库跨库查询的一些思路

  4. 一文读懂阿里大中台、小前台战略

作者简介猿芯,一枚简单的北漂程序员。喜欢用简单的文字记录工作与生活中的点点滴滴,愿与你一起分享程序员灵魂深处真正的内心独白。我的微信号:WooolaDunzung,公众号【猿芯输入 1024 ,有份面试惊喜送给你哦

< END >

【猿芯】

微信扫描二维码,关注我的公众号。

分享不易,莫要干想,如果觉得有点用的话,动动你的发财之手,一键三连击:分享、点赞、在看,你们的鼓励是我分享优质文章的最强动力 ^_^

分享、点赞、在看,3连3连!

老鸟必修代码精简技能:Lambda表达式相关推荐

  1. 表达式类型的实现_程序员如何使代码简洁,Lambda表达式入门之四大引用(下篇)...

    享学课堂特邀作者:老顾转载请声明出处! 前言 上一篇介绍了lambda表达式的语法,今天老顾继续介绍 Lambda类型 Lambda表达式可以被当做是一个Object.Lambda表达式的类型,叫做& ...

  2. java是如何简化成一行代码的?-----Lambda表达式初识

    嗨喽-小伙伴们,早上好,中午好,晚上好呀, 之前有一个小伙伴给我发了一段代码,说是看不懂,这段代码是这样的: public class Aha {public static void main(Str ...

  3. C# 从CIL代码了解委托,匿名方法,Lambda 表达式和闭包本质

    前言 C# 3.0 引入了 Lambda 表达式,程序员们很快就开始习惯并爱上这种简洁并极具表达力的函数式编程特性. 本着知其然,还要知其所以然的学习态度,笔者不禁想到了几个问题. (1)匿名函数(匿 ...

  4. 很适合装逼的代码(Lambda表达式)

    Lambda表达式概述: Lambda表达式是JDK1.8开始之后的新技术,是一种代码的新语法,是一种特殊写法.作用:"核心目的是为了简化匿名内部类的代码写法". Lambda表达 ...

  5. Java Lambda表达式入门

    本文转自:http://blog.csdn.net/renfufei... 转载请注明出处 原文链接: Start Using Java Lambda Expressions 下载示例程序 Examp ...

  6. java拉姆达表达式事例,Java Lambda表达式详解和实例

    简介 Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体( ...

  7. Java 8th 函数式编程:lambda 表达式

    Lambda 表达式是 java 8th 给我们带来的几个重量级新特性之一,借用 lambda 表达式可以让我们的程序设计更加简洁.最近新的项目摒弃了 6th 版本,全面基于 8th 进行开发,本文将 ...

  8. Java中Lambda表达式的使用(转)

    https://www.cnblogs.com/franson-2016/p/5593080.html 简介 (译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖" ...

  9. 【Java】反射、枚举、Lambda表达式

    一.反射 1 定义 2 用途(了解) 3 反射基本信息 4 反射相关的类(重要) 4.1 Class类(反射机制的起源 ) 4.1.1 Class类中的相关方法(方法的使用方法在后边的示例当中) 4. ...

最新文章

  1. sed和awk有什么区别? [关闭]
  2. Linux2.6内核--抢占
  3. 除了负载均衡,Nginx还可以做很多,限流、缓存、黑白名单等
  4. sqlserver全文索引问题
  5. 改了两天的bug,一个JWT解决了。。。
  6. aes加密算法python语言实现_python-AES加密解密
  7. 年仅 5 岁的 Rust 如何成为最受欢迎的编程语言?
  8. 网络协议:TCP/IP协议,你看懂了吗?
  9. paroot忘记root密码
  10. jquery 获取父窗口的元素、父窗口、子窗口
  11. 计生专干招聘计算机,请求解决招聘计生专干待遇
  12. can't connect local MySql Server though socket /tmp如何解决
  13. c语言程序最简单例子,简单C语言程序的例子
  14. SAP APO IPPE 基础数据(汽车行业)
  15. 读书笔记3|使用Python,networkx对卡勒德胡赛尼三部曲之——《群山回唱》人物关系图谱绘制
  16. dx.jar bad class file magic (cafebabe) or version (0034.0000)
  17. Maven - 2、安装、配置、mvn运行过程详解
  18. pythonapi说明_python API接口说明
  19. 风光互补发电系统实训装置QY-GF05
  20. 凭什么是你从新星计划里面脱颖而出?答:凭这五点

热门文章

  1. 人生不止一个答案,每个人都有自己的战场
  2. 数字人民币预付式消费的监管之道,智能合约能不能解决所有问题?
  3. [转]Windows Sysinternals 微软官方免费的极品实用绿色小工具合集,绝对值得你收藏
  4. RotateAnimation类:旋转变化动画类
  5. 【Python实战】Python采集二手车数据——超详细讲解
  6. 2022年亏损超10亿,告别野蛮成长的众安在线急需新“引擎”
  7. C语言函数调用指针交换值
  8. 题目1029:魔咒词典
  9. ! [rejected] master - master (non-fast-forward)
  10. 06 go启动生命周期M0和G0