Lambda 表达式,即函数式编程是 JDK8 的一个新特性,也被称为闭包,Lambda表达式允许把函数作为一个方法的参数,即行为参数化,函数作为参数传递进方法中。

Lambda表达式可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

总结就是:使用不可变值与函数,函数对不可变值进行处理,映射成另一个值。


一、什么是函数式接口

函数接口是只有一个抽象方法的接口,用作 Lambda 表达式的类型。使用@FunctionalInterface注解修饰的类,编译器会检测该类是否只有一个抽象方法或接口,否则,会报错。可以有多个默认方法,静态方法。

lambda 表达式是一小段代码,它接受参数并返回一个值。Lambda 表达式类似于方法,但它们不需要名称,并且可以直接在方法体中实现。

语法:最简单的 lambda 表达式包含一个参数和一个表达式:

  • 零参数:

() -> System.out.println("零参数 lambda");
  • 一个参数:

p -> System.out.println("一个参数:" + param);
  • 多个参数:

(p1 [,p2,p3,....pn]) -> System.out.println("多个参数:" + p1 + ", " + p2 + ... + pn);

上面的表达式有一定的限制。它们要么返回一个值要么执行一段方法,并且它们不能包含变量、赋值或语句,例如if or for 。为了进行更复杂的操作,可以使用带有花括号的代码块。如果 lambda 表达式需要返回一个值,那么代码块应该有一个return语句。


(parameter1, parameter2) -> { code block [return] }

1、方法引用

  • 类 :: 静态方法

Consumer<String> c = [ (s) -> System.out.println(s);  <=>  System.out::println; ]
  • 对象 :: 实例方法

List<String> list = Lists.newArrayList();
Consumer<String> c = [ (e) => list.add(e);  <=>  list::add; ]
  • 构造器 :: new

Supplier<List<String>> s = [ () -> new ArrayList<>(); <=> ArrayList::new; ]

2、@FunctionalInterface注解

有且只有一个抽象方法的接口被称为函数式接口,函数式接口适用于函数式编程的场景,Lambda就是Java中函数式编程的体现,可以使用Lambda表达式创建一个函数式接口的对象,一定要确保接口中有且只有一个抽象方法,这样Lambda才能顺利的进行推导。

与@Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface 。该注解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法(equal和hashcode方法不算),否则将会报错。但是这个注解不是必须的,只要符合函数式接口的定义,那么这个接口就是函数式接口。

3、 java8自带的常用函数式接口。

4、简单的例子

package com.biyu.study.lambda;import com.biyu.study.lambda.bean.Employee;import java.math.BigDecimal;
import java.util.function.*;public class Test {public static void main(String[] args) {Predicate<Integer> predicate = x -> x > 20;Employee employee = new Employee("Lily", "女", 18);System.out.println("Lily的大于18岁吗?:" + predicate.test(employee.getAge()));Consumer<String> consumer = System.out::println;consumer.accept("Hello World");Function<Employee, String> function = Employee::getName;String name = function.apply(employee);System.out.println(name);Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());System.out.println(supplier.get());UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;Boolean apply2 = unaryOperator.apply(true);System.out.println(apply2);BinaryOperator<Integer> operator = (x, y) -> x * y;Integer integer = operator.apply(2, 3);System.out.println(integer);test(() -> "函数式接口");}/*** 自定义函数式接口使用** @param worker*/public static void test(Worker worker) {String work = worker.work();System.out.println(work);}public interface Worker {String work();}
}

以上演示了lambda接口的使用及自定义一个函数式接口并使用。

二、Lambda 流的常用方法

1、ForEach

集合的遍历 forEach 方法:

public static void testForEach(){List<String> list = new ArrayList<String>() {{add("1");add("2");add("3");}};list.forEach(s-> System.out.println(s));}

2、Collect

将操作后的对象转化为新的对象:

public static void testCollect(){List<String> list = new ArrayList<String>() {{add("1");add("2");add("2");}};//转换为新的listList newList = list.stream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());System.out.println(newList);}

3、Filter

Filter 为过滤的意思,只要满足 Filter 表达式的数据就可以留下来,不满足的数据被过滤掉。

public static void testFilter() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("3");}};List<String> filtered = list.stream()// 过滤掉我们希望留下来的值// 表示我们希望字符串是 1 能留下来// 其他的过滤掉.filter(str -> "1".equals(str)).collect(Collectors.toList());System.out.println(filtered);}

4、Map

map 方法可以让我们进行一些流的转化,比如原来流中的元素是 A,通过 map 操作,可以使返回的流中的元素是 B。

public static void testMap() {List<String> list = new ArrayList<String>() {{add("A");add("B");add("C");}};//通过 map 方法list中元素转化成 小写List<String> strLowerList = list.stream().map(str -> str.toLowerCase()).collect(Collectors.toList());System.out.println(strLowerList);}

5、MapToInt

mapToInt 方法的功能和 map 方法一样,只不过 mapToInt 返回的结果已经没有泛型,已经明确是 int 类型的流了。

public static void testMapToInt() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("3");}};List<Integer> intList=list.stream().mapToInt(s->Integer.valueOf(s))// 一定要有 mapToObj,因为 mapToInt 返回的是 IntStream,因为已经确定是 int 类型了,所以没有泛型的,// 而 Collectors.toList() 强制要求有泛型的流,所以需要使用 mapToObj方法返回有泛型的流.mapToObj(s->s).collect(Collectors.toList());System.out.println(intList);Double sum = list.stream().mapToDouble(s->Double.valueOf(s))// DoubleStream/IntStream 有许多 sum(求和)、min(求最小值)、max(求最大值)、average(求平均值)等方法.sum();System.out.println(sum);}

6、Distinct

distinct 方法有去重的功能:

public static void testDistinct() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("2");add("5");add("3");}};List<Integer> intList = list.stream().map(s -> Integer.valueOf(s)).distinct().collect(Collectors.toList());System.out.println(intList);}

7、Sorted

Sorted 方法提供了排序的功能,并且允许我们自定义排序。

public static void testSorted() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("-1");add("9");add("11");add("27");add("0");}};List<Integer> intList = list.stream().map(s -> Integer.valueOf(s))// 等同于 .sorted(Comparator.naturalOrder()) 自然排序.sorted().collect(Collectors.toList());System.out.println(intList);// 自定义排序器intList =list.stream().map(s -> Integer.valueOf(s))// 反自然排序.sorted(Comparator.reverseOrder()).collect(Collectors.toList());System.out.println(intList);}

8、groupingBy

groupingBy 是能够根据字段进行分组,toMap 是把 List 的数据格式转化成 Map 的格式。

public static void testGroupBy() {List<String> list = new ArrayList<String>() {{add("iphone 4s");add("iphone 6");add("iphone 12");add("iphone 14");add("xiaomi");add("huawei");add("oppo");}};Map<String, List<String>> strList = list.stream().collect(Collectors.groupingBy(s -> {if (s.startsWith("iphone")){return "iphone";} else {return "other";}}));System.out.println(strList);}

9、FindFirst

findFirst 表示匹配到第一个满足条件的值就返回:

public static void testFindFirst() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("2");}};list.stream().filter(s -> "2".equals(s)).findFirst().get();// 防止空指针list.stream().filter(s -> "2".equals(s)).findFirst()// orElse 表示如果 findFirst 返回 null 的话,就返回 orElse 里的内容.orElse("3");Optional<String> str = list.stream().filter(s -> "2".equals(s)).findFirst();// isPresent 为 true 的话,表示 value != nullif (str.isPresent()) {return;}}

10、Reduce

reduce 方法允许我们在循环里面叠加计算值:

public static void testReduce() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("3");}};int sum = list.stream().map(s -> Integer.valueOf(s))// s1 和 s2 表示循环中的前后两个数.reduce((s1, s2) -> s1 + s2).orElse(0);System.out.println(sum);sum =list.stream().map(s -> Integer.valueOf(s))// 第一个参数表示基数,会从 100 开始加.reduce(100, (s1, s2) -> s1 + s2);System.out.println(sum);}

11、Peek

peek 方法很简单,我们在 peek 方法里面做任意没有返回值的事情,比如打印日志:

public static void testPeek() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("3");}};list.stream().map(s -> Integer.valueOf(s)).peek(s -> System.out.println(s)).collect(Collectors.toList());}

12、Limit

limit 方法会限制输出值个数,入参是限制的个数大小:

public static void testLimit() {List<String> list = new ArrayList<String>() {{add("1");add("2");add("3");add("4");add("5");}};List<Integer> integers= list.stream().map(s -> Integer.valueOf(s)).limit(3L).collect(Collectors.toList());System.out.println(integers);}

13、Max,Min

通过 max、min 方法,可以获取集合中最大、最小的对象。

public static void testMaxMin() {List<String> list = new ArrayList<String>() {{add("1");add("3");add("2");add("-12");add("99");}};String maxNum = list.stream().max(Comparator.comparing(s -> Integer.valueOf(s))).get();String minNum = list.stream().min(Comparator.comparing(s -> Integer.valueOf(s))).get();System.out.println(maxNum);System.out.println(minNum);}

三、写在最后

本章节主要从实际使用讲述了常用的方法及流,文中例子主要是为了讲解较为简单,大家可以去使用java8重构自己现有的代码,自行领会lambda的奥妙使用。java8可以很清晰表达你要做什么,代码也很简洁。

【Java基础】Java Lambda表达式详解相关推荐

  1. java lambda表达式详解_Java8新特性Lambda表达式详解

    课程目标: 通过本课程的学习,详细掌握Java8新特性之Lambda表达式: 适用人群:有Java基础的开发人员: 课程概述:从Java 8出现以来lambda是最重要的特性之一,它可以让我们用简洁流 ...

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

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

  3. 【Java基础】HashMap原理详解

    [Java基础]HashMap原理详解 HashMap的实现 1. 数组 2.线性链表 3.红黑树 3.1概述 3.2性质 4.HashMap扩容死锁 5. BATJ一线大厂技术栈 HashMap的实 ...

  4. java基础之lambda表达式

    java基础之lambda表达式 1 什么是lambda表达式 lambda表达式是一个匿名函数,允许将一个函数作为另外一个函数的参数,将函数作为参数传递(可理解为一段传递的代码). 2 为什么要用l ...

  5. java基础与案例开发详解 pdf下载_Java基础与案例开发详解(张孝祥) pdf_IT教程网...

    资源名称:Java基础与案例开发详解(张孝祥) pdf 第1.2和3章介绍Java环境的安装配置,Java程序的开发过程和Java语言的基础语法. 第4章介绍数组和常用算法的相关知识. 第5章和6章介 ...

  6. Java8 Lambda表达式详解手册及实例

    先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号"程序新视界",好好系列的学习一下 ...

  7. Java 8 Lambda 表达式详解

    版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某 ...

  8. Java8 lambda表达式详解

    Scala中函数是一等公民,有大量的函数式编程,而Java1.8的新特性也加入了函数式编程,转载如下. 关键词:函数式接口.lambda表达式  作用:函数式编程.替换匿名内部类(利用lambda实现 ...

  9. Lambda表达式详解

    01:Lambda表达式 Lambda表达式标准格式: 由三部分组成: a.一些参数 b.一个箭头 c.一段代码 格式: (参数列表) ->{ 一些重写方法的代码}; 解释说明格式: ():接口 ...

最新文章

  1. 冒号课堂 编程范式与OOP思想
  2. 关于eigrp-FSM有限状态机的资料
  3. 验证数字的正则表达式集
  4. docker安装PostgreSQL
  5. c++中的输入输出方法
  6. hdu 5497 Inversion(树状数组)
  7. asp关于从utf8页面到gb2312页面出现乱码得解决
  8. VB2005.Net 环境下使用Jmail组件发送邮件
  9. python解密_Python解密
  10. 【2016年第3期】大数据治理的数据模式与安全
  11. 利用系统级别的光谱成像技术分析细胞器的互作组学
  12. PAT (Basic Level) Practice1019 数字黑洞
  13. easyui form表单提交标准格式
  14. EGS5在linux系统下安装过程
  15. deepin 应用市场安装软件失败_深度商店软件无法安装问题解决方案
  16. 计算机能不能升级固态硬盘,笔记本升级固态硬盘后会怎样?秒懂
  17. ubuntu 20.04 安装 QQ 和 Wechat 及其卸载, 解决微信不能发图片, 输入框输入中文显示方块问题
  18. Excel简单使用宏
  19. PT6303加充电电路的一套原理图
  20. 小米手机短信拦截转发失败原因

热门文章

  1. 游戏辅助 -- DLL窗口实现人物走动
  2. xbin目录及toolbox,toybox
  3. AxureRP使用技巧
  4. 贵阳大数据草根创新赛启动
  5. 修改oracle序列最小值,Oracle如何使用序列 Oracle序列使用教程
  6. android app性能优化大汇总(内存性能优化)
  7. 创建简单的MVC框架1-Modle篇之PDO库
  8. 如何去除table的边框_怎么把table的外面的边框去掉
  9. Vue表格中手机号码的隐藏与分组
  10. SpringBoot与Spring的区别