美文网首页代码改变世界大数据
简化业务代码开发:看 Lambda 表达式如何将代码封装为数据

简化业务代码开发:看 Lambda 表达式如何将代码封装为数据

作者: 华为云开发者联盟 | 来源:发表于2021-01-18 11:41 被阅读0次

摘要:在云服务业务开发中,善于使用代码新特性,往往能让开发效率大大提升,这里简单介绍下lambad表达式及函数式接口特性。

在云服务业务开发中,善于使用代码新特性,往往能让开发效率大大提升,这里简单介绍下lambad表达式及函数式接口特性。

1.Lambda 表达式

Lambda表达式也被称为箭头函数、匿名函数、闭包。他允许把函数作为一个方法的参数(函数作为参数传递到方法中),体现出轻量级函数式编程思想。

为什么引入lambda?

Model Code as Data,编码及数据,尽可能轻量级的将代码封装为数据。

解决方案:接口&实现类(匿名内部类)

存在问题:语法冗余,this关键字、变量捕获、数据控制等

不是解决未知问题的新技术

对现有问题的语义化优化

需要根据实际需求考虑性能问题

2.函数式接口(Functional Interface)

函数式接口就是Java类型系统中的接口,是只包含一个抽象方法的特殊接口(可以有很多非抽象方法)。

语言化检测注解:@FunctionalInterface 检测合法性

java1.8支持接口内包含:抽象方法、默认接口方法、静态接口方法、来自Object继承的方法

JDK 1.8 之前已有的函数式接口:

 java.lang.Runnable

java.util.concurrent.Callable

java.security.PrivilegedAction

java.util.Comparator

java.io.FileFilter

more

JDK 1.8 新增加的函数接口:

java.util.function

3.lambda表达式的基本语法

基本语法

声明:就是和lambda表达式绑定的接口类型

参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数个数及顺序一致。

操作符:->

执行代码块:包含在一对大括号中,出现在操作符号的右侧

[接口声明] = (参数) -> {执行代码块};

总结:

lambda表达式,必须和接口进行绑定。

lambda表达式的参数,可以附带0个到n个参数,括号中的参数类型可以不用指定,jvm在运行时,会自动根据绑定的抽象方法中的参数进行推导。

lambda表达式的返回值,如果代码块只有一行,并且没有大括号,不用写return关键字,单行代码的执行结果,会自动返回。 如果添加了大括号,或者有多行代码,必须通过return关键字返回执行结果。

变量捕获

匿名内部类型变量捕获

lambda表达式变量捕获

总结:Lambda表达式优化了匿名内部类类型中的this关键字,不再单独建立对象作用域,表达式本身就是所属类型对象的一部分,在语法语义上使用更加简洁。

类型检查

对于语法相同的表达式,Jvm在运行的过程中,在底层通过解释及重构,进行类型的自动推导。

表达式类型检查

参数类型检查

方法重载

总结:出现方法重载的类型中参数都是函数式接口的情况,需使用匿名内部类实现替代lambda表达式。

底层构建原理

javac Test.java

javap -p Test.class (javap反解析工具 -p显示所有类与成员)

 java -Djdk.internal.lambda.dumpProxyClasses Test

声明一个私有静态方法,对Lambda表达式做一个具体的方法实现

声明一个final内部类型并实现接口

在实现接口后的重写方法中利用外部类调用该私有静态方法

 4.方法引用

方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

静态方法引用

实例方法引用

构造方法引用

5.Stream

新添加的Stream流—是一个来自数据源的元素队列并支持聚合操作。把真正的函数式编程风格引入到Java中。

不存储数据,也不修改原始源。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

// 1. for循环实现 List list = new ArrayList(); for (String s : list) { if (s.length() > 3) { lista.add(s); } } System.out.println(lista);

几者关系

lambda表达式是传统方法的语法糖,简化并且改造传统内部类实现设计方案的另一种实现模式。

方法引用又是lambda基础上的语法糖,和Stream没有关系,简化方法调用的。

Stream是针对数据和集合的强化优化操作,可以和lambda结合起来简化编码过程。

常见API介绍

1.聚合操作

2.Stream的处理流程

数据源

数据转换[可一到多次转换]

获取结果

3.获取Stream对象

从集合或者数组中获取

Collection.stream(), 如list.stream()

Collection.parallelstream(), 获得支持并发处理的流

Arrays.stream(T t)

BufferReader

BufferReader.lines()-> stream()

静态工厂

java.util.stream.IntStream.range()..

java.nio.file.Files.walk()..

自定构建

java.util.Spliterator

更多的方式

Random.ints()

Pattern.spiltAsStream()..

4.中间操作API{intermediate}:

操作结果是一个Stream对象,所以中间操作可有一个或多个连续的中间操作,需要注意的是中间操作只记录操作方式,不做具体执行,直到结束操作发生时,才做数据的最终执行。

中间操作就是业务逻辑处理

操作过程分为有状态和无状态

无状态:即处理数据时,不受前置中间操作的影响

map/filter/peek/parallel/sequential/unordered

有状态:即处理数据时,受前置中间操作的影响

distant/sorted/limit/skip

5.终结操作|结束操作{Terminal}

一个steam对象只能有一个Terminal操作。这个操作不可逆,一旦发生,就会真实处理数据生成对应结果

非短路操作:当前的Stream对象必须处理完集合中所有的数据,才能得到处理结果

forEach/forEachOrdered/toArray/reduce/collect/min/max/count/iterator

短路操作:当前的Stream对象在处理过程中,一旦满足某个条件,就可以得到结果

    anyMatch/AllMatch/noneMatch/findfirst/findAny等

short-circuiting : 在无限大的stream 中返回有限大的stream 需要包含短路操作是有必要的

Stream转换

Stream常见操作

6.案例

问题一:将实例List转化为Map

对于List来说,我需要将其形变为Map<Table.id,Table>,用如下流处理代码

问题二:将集合分成若干类别

使用问题一中的Table类,对于List,我需要将其按照partitionFlag分类,Collector提供两种方法partitioningBy()、groupingBy()。前者分成满足条件与不满足条件两类,后者可按条件分成若干类别的Map。

有的时候,我们关注的不光是元素还有元素的个数,流处理可以再进行后期处理。

Map<Boolean, List<Table>> tablePartition = tableList 

.stream().collect(Collectors.partitioningBy(item -> 

item.getPartitionFlag() == true,Collectors.counting()));

可输出符合要求的个数。

groupingBy()可对字符串长度分组。

List strings=Arrays.asList(“this”,”is”,”a”,”test”);Map> stringsMap = strings        .stream().collect(Collectors.groupingBy(String::length);复制代码

结果输出多分类的map,key值为字符串长度。

注意:如果是从数据库获取数据,务必将分组操作放在数据库中执行,java8新增方法只适合处理内存中的数据。

问题三:从list中得到某个特定的对象

获得List中columnNum最多的table对象

tableList.stream().sorted(comparingInt(Table::getColumnNum)).collect(Collectors.toList()).get(tableList.size()-1);复制代码

添加中间操作reversed() 可获取最小columnNum的对象

问题四: 得到Map<Table,Table.columnNum>中最大columnNum的table

List>list=newArrayList(tableMap.entrySet());Collections.sort(list, (o1, o2) -> (o2.getValue() - o1.getValue()));list.get(0).getKey();

7.性能与安全

串行Stream的性能小于传统的for循环、 迭代器

并行Stream的性能与传统的for循环、 迭代器差不多,在处理对象(复杂数据类型)的情况下,并行性能最佳

本文分享自华为云社区《如何善用函数式接口简化云服务业务代码开发》,原文作者:luanzhen 。

相关文章

  • 简化业务代码开发:看 Lambda 表达式如何将代码封装为数据

    摘要:在云服务业务开发中,善于使用代码新特性,往往能让开发效率大大提升,这里简单介绍下lambad表达式及函数式接...

  • Lambda表达式

    "Lambda表达式"是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码...

  • Lambda 表达式

    1 Lambda 表达式 Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此...

  • java8Lambda表达式如何使用

    java8Lambda表达式如何使用 lamda表达式是java8新特性,优点简化代码,降低代码重复率。 语法格式...

  • Kotlin基础 -- 2

    五、Lambda编程 1.Lambda表达式和成员引用 Lambda简介:作为函数参数的代码块。可以理解为简化表达...

  • Java8 Lambda表达式初探

    Lambda表达式的浅显理解 使用Lambda表达式可以简化我们的代码 解决无法获取非final对象的问题 在有L...

  • 2021-07-03

    今天看了java8中Lambda表达式的相关视频并且跟着视频敲了代码,收获最大的就是知道Lambda表达式简化了匿...

  • Java Lambda 表达式不为人熟知的特性

    Lambda 表达式是 Java 8 的新语法,可以极大地简化代码,增强语言的表达力。这里不赘述 Lambda 表...

  • 2018-05-11Lambda表达式

    Lambda表达式入门 Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建只...

  • 线程池很容易理解的

    线程池介绍 并发队列 线程池原理分析 自定义线程池 文中部分代码使用 lambda 表达式以简化代码。 线程池 什...

网友评论

    本文标题:简化业务代码开发:看 Lambda 表达式如何将代码封装为数据

    本文链接:https://www.haomeiwen.com/subject/bfotzktx.html