Lambda 表达式

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

JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

可以对某些匿名内部类的写法进行简化,它是函数式编程思想的一个重要体现,不用关注是什么对象,而是更关注对数据进行了什么操作。

基本格式

  1. (参数列表)->{代码}

范例

范例一:

在创建线程并启动时可以使用匿名内部类的写法;

  • 匿名内部类方式:
  1. new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println(Thread.currentThread());
  5. }
  6. }).start();
  • Lambda方式:
  1. new Thread(() -> {
  2. System.out.println(Thread.currentThread());
  3. }).start();

范例二:

IntBinaryOperator是一个接口,使用匿名内部类的写法调用该方法;

  • 匿名内部类方式:
  1. public static int calculateNum(IntBinaryOperator operator) {
  2. int a = 10;
  3. int b = 20;
  4. return operator.applyAsInt(a, b);
  5. }
  6. @Test
  7. public void testLambda2() {
  8. int i = calculateNum(new IntBinaryOperator() {
  9. @Override
  10. public int applyAsInt(int left, int right) {
  11. return left + right;
  12. }
  13. });
  14. System.out.println(i);
  15. }
  • Lambda方式:
  1. public static int calculateNum(IntBinaryOperator operator) {
  2. int a = 10;
  3. int b = 20;
  4. return operator.applyAsInt(a, b);
  5. }
  6. @Test
  7. public void testLambda2() {
  8. int i = calculateNum((int left, int right) -> {
  9. return left + right;
  10. });
  11. System.out.println(i);
  12. }

范例三:

IntPredicate是一个接口。先使用匿名内部类的写法调用该方法;

  • 匿名内部类方式:
  1. public static void printNum(IntPredicate predicate) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. if (predicate.test(i)) {
  5. System.out.println(i);
  6. }
  7. }
  8. }
  9. @Test
  10. public void testLambda3() {
  11. printNum(new IntPredicate() {
  12. @Override
  13. public boolean test(int value) {
  14. return value % 3 == 0;
  15. }
  16. });
  17. }
  • Lambda方式:
  1. public static void printNum(IntPredicate predicate) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. if (predicate.test(i)) {
  5. System.out.println(i);
  6. }
  7. }
  8. }
  9. @Test
  10. public void testLambda3() {
  11. printNum((int value) -> {
  12. return value % 3 == 0;
  13. });
  14. }

范例四:

Function是一个接口,先使用匿名内部类的写法调用该方法;

  • 匿名内部类方式:
  1. public static <R> R typeConver(Function<String, R> function) {
  2. String str = "1235";
  3. R result = function.apply(str);
  4. return result;
  5. }
  6. @Test
  7. public void testLambda4() {
  8. Integer result = typeConver(new Function<String, Integer>() {
  9. @Override
  10. public Integer apply(String s) {
  11. return Integer.valueOf(s);
  12. }
  13. });
  14. System.out.println(result);
  15. }
  • Lambda方式:
  1. public static <R> R typeConver(Function<String, R> function) {
  2. String str = "1235";
  3. R result = function.apply(str);
  4. return result;
  5. }
  6. @Test
  7. public void testLambda4() {
  8. Integer result = typeConver((String s) -> {
  9. return Integer.valueOf(s);
  10. });
  11. System.out.println(result);
  12. }

范例五:

IntConsumer是一个接口,先使用匿名内部类的写法调用该方法;

  • 匿名内部类方式:
  1. public static void foreachArr(IntConsumer consumer) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. consumer.accept(i);
  5. }
  6. }
  7. @Test
  8. public void testLambda5() {
  9. foreachArr(new IntConsumer() {
  10. @Override
  11. public void accept(int value) {
  12. System.out.println(value);
  13. }
  14. });
  • Lambda方式:
  1. public static void foreachArr(IntConsumer consumer) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. consumer.accept(i);
  5. }
  6. }
  7. @Test
  8. public void testLambda5() {
  9. foreachArr((int value) -> {
  10. System.out.println(value);
  11. });
  12. }

省略规则

  • 参数类型可以省略;
  1. public static void foreachArr(IntConsumer consumer) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. consumer.accept(i);
  5. }
  6. }
  7. @Test
  8. public void testLambda5() {
  9. foreachArr((value) -> {
  10. System.out.println(value);
  11. });
  12. }
  • 方法体只有一句代码时大括号return和唯一一句代码的分号可以省略;
  1. public static void foreachArr(IntConsumer consumer) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. consumer.accept(i);
  5. }
  6. }
  7. @Test
  8. public void testLambda5() {
  9. foreachArr((value) -> System.out.println(value));
  10. }
  • 方法只有一个参数时小括号可以省略;
  1. public static void foreachArr(IntConsumer consumer) {
  2. int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. for (int i : arr) {
  4. consumer.accept(i);
  5. }
  6. }
  7. @Test
  8. public void testLambda5() {
  9. foreachArr(value -> System.out.println(value));
  10. }
  • 以上这些规则都记不住也可以省略不记,可通过idea的replaceLambda表达式快速生成lambda表达式;

Stream 流

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作。

Stream - 特性

Stream可以由数组或集合创建,对流的操作分为两种:

  • 中间操作,每次返回一个新的流,可以有多个;
  • 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

Stream特性:

  • stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果;

  • stream不会改变数据源,通常情况下会产生一个新的集合或一个值;

  • stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

Stream - 创建方式

Stream创建方式有三种:

  • 通过 java.util.Collection.stream() 方法用集合创建流;

  • 使用java.util.Arrays.stream(T[] array)方法用数组创建流;

  • 使用Stream的静态方法:of()、iterate()、generate()。

  1. import java.util.Arrays;
  2. import java.util.List;
  3. import java.util.concurrent.atomic.AtomicInteger;
  4. import java.util.stream.Collectors;
  5. import java.util.stream.IntStream;
  6. import java.util.stream.Stream;
  7. /**
  8. * @author hos
  9. * @Createdate 2022/3/21 14:40
  10. */
  11. public class StreamCreateType {
  12. public static void main(String[] args) {
  13. /**
  14. * Stream 流的创建有3种方式
  15. * 1. Collection.stream()方法用集合创建
  16. * 2. Arrays.stream(T[] array) 方法用数组创建
  17. * 3. 使用Stream的静态方法:of()、iterate()、generate()
  18. */
  19. //方式一: Collection.stream()方法用集合创建
  20. List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9");
  21. // 创建一个顺序流
  22. Stream<String> stream = list.stream();
  23. // 创建一个并行流
  24. Stream<String> stringStream = list.parallelStream();
  25. List<String> collect = stringStream.collect(Collectors.toList());
  26. //方式二: Arrays.stream(T[] array) 方法用数组创建
  27. int[] array = {1, 2, 3, 4, 5};
  28. IntStream stream1 = Arrays.stream(array);
  29. System.out.println(stream1.max().getAsInt());
  30. //方式三: 使用Stream的静态方法:of()、iterate()、generate()
  31. Stream<Integer> intStream = Stream.of(1, 2, 3, 4, 5, 6);
  32. Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
  33. // 0 3 6 9
  34. stream2.forEach(System.out::println);
  35. AtomicInteger m = new AtomicInteger(10);
  36. Stream<Integer> stream3 = Stream.generate(()-> m.getAndIncrement()).limit(3);
  37. //10 11 12
  38. stream3.forEach(System.out::println);
  39. }
  40. }

Stream - 使用

中间操作

map

map,可以将一个流的元素按照一定的映射规则映射到另一个流中;

map,接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

filter

filter,对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中;

filter,按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

distinct

distinct,去除流中的重复元素;

sorted

sorted(),自然排序,流中元素需实现Comparable接口;

sorted(Comparator com),Comparator排序器自定义排序。

limit

limit,可以设置流的最大长度,超出的部分将被抛弃;

skip

skip,跳过流中的前n个元素,返回剩下的元素;

flatMap

flatMap,接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流;

map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

终结操作

forEach

forEach方法,通过 lambda 表达式的方式遍历集合中的元素;

forEach,对流中的元素进行遍历操作,通过传入的参数去指定对遍历到的元素进行什么具体操作。

count

count,用来获取当前流中元素的个数;

max&min

max&min,可以用来或者流中的最值。

collect

collect,把当前流转换成一个集合;

collect,把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合;流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。

reduce

reduce,把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作;

reduce,对流中的数据按照你指定的计算方式计算出一个结果。

Lambda8 表达式的更多相关文章

  1. 【.net 深呼吸】细说CodeDom(2):表达式、语句

    在上一篇文章中,老周厚着脸皮给大伙介绍了代码文档的基本结构,以及一些代码对象与CodeDom类型的对应关系. 在评论中老周看到有朋友提到了 Emit,那老周就顺便提一下.严格上说,Emit并不是针对代 ...

  2. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  3. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  4. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  5. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  6. Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)

    作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...

  7. SQL Server-表表达式基础回顾(二十四)

    前言 从这一节开始我们开始进入表表达式章节的学习,Microsoft SQL Server支持4种类型的表表达式:派生表.公用表表达式(CTE).视图.内嵌表值函数(TVF).简短的内容,深入的理解, ...

  8. 立即执行函数表达式(IIFE)

    原文地址:benalman.com/news/2010/11/immediately-invoked-function-expression/ 译者:nzbin 也许你还没有注意到,我是一个对术语比较 ...

  9. javascript:逆波兰式表示法计算表达式结果

    逆波兰式表示法,是由栈做基础的表达式,举个例子: 5 1 2 + 4 * + 3 -  等价于   5 + ((1 + 2) * 4) - 3 原理:依次将5 1 2 压入栈中, 这时遇到了运算符 + ...

随机推荐

  1. _IO_2_1_stdin_ 任意写及对 _IO_2_1_stdout_ 任意读的补充

    之前写过一篇 IO_FILE--leak 任意读,但是在学习的时候偷懒了,没有深入去看,这次碰到 winmt 师傅出的题,就傻眼了,故再写一篇博客来记录一下. 例题 ctfshow Incomplet ...

  2. 快速构建 React 开发环境

    使用 create-react-app 快速构建 React 开发环境 create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境. cre ...

  3. Jquery mobiscroll 移动设备(手机)wap日期时间选择插件以及滑

    $(function () { var currYear = (new Date()).getFullYear(); var opt={}; //opt.date = {preset : 'date' ...

  4. ASP.NET Core框架探索(一)

    今天我们来结合源码来探究一下ASP.NET CORE Web框架的运行原理. 可以先整体看一下下面这张基于源码分析过程的一个总结大纲,包含各环节完成的关键步骤: 下面我们将一起来结合源码探索启动一个A ...

  5. IntelliJ IDEA 中打包时报aspose-cells错误缺失

    异常情况 在本地执行word转换为pdf是没有问题,但是在maven中提示错误: 解决方案 将com\aspose\aspose-cells\9.0.0下除了[aspose-cells-9.0.0.j ...

  6. Lua中如何实现类似gdb的断点调试—06断点行号检查与自动修正

    前面两篇我们对性能做了一个优化,接下来继续来丰富调试器的特性. 我们前面提到过,函数内并不是所有行都是有效行,空行和注释行就不是有效行.我们之前在添加断点的时候,并没有对行号进行检查,任何行号都能成功 ...

  7. laravel7 ajax H-ui框架添加数据至数据库

    1:定义路由: //租房 Route::resource('house','fang\FangattrController'); 2:控制器访问前端框架: public function create ...

  8. 新建SpringBoot项目报错

    新建一个Springboot项目时,当勾选了SQL相关的依赖(如引入了jpa 或MyBatis依赖),直接启动项目时报错 原因:没有配置数据库相关的属性,如 url driver 等 解决办法:在ap ...

  9. [MySQL]MySQL8.0的一些注意事项以及解决方案

    MySQL8.0 注意事项以及解决方案 1. MySQL8.0 修改大小写敏感配置 天坑MySQL8.0! 在安装后, 便无法通过修改配置文件,重启服务,或者执行sql来更改数据库配置, 要想配置的话 ...

  10. Objective-C 基础教程第七章,深入理解Xcode

    目录 Object-C 基础教程第七章,深入理解Xcode 0x00 前言 0x01 创建工程界面 0x02 主程序界面 ①顶部 Top Test(测试) Profile(动态分析) Analyze( ...