函数式编程

函数式编程是一种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 函数式编程是"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。

lambda表达式

JSR-335首次定义了在Java中使用lambda表达式的基本规范,当前的实现就是针对JSR-335规范的。 lambda表达式是一种紧凑的、传递行为的方式。Lambda表达式本质上是为了解决方便的将代码作为数据传递的难题。从本质上讲lambda表达式就是一种将行为参数化的操作。

在JDK8之前,需要利用匿名内部类来实现的传递行为的操作,现在可以用lambda表达式来实现了。 从编码的角度讲,lambda表达式是一个代码块,以及必须传入代码的变量规范。

由于规范基本一致,所以Java中的lambda表达式和JavaScript中的在使用上几乎完全一样。所差别的只是胖箭头和瘦箭头而已。当然由于语言特性的问题,两种lambda表达式的实际差距还是很大的,这种差距表现在:在Java中,lambda表达式本身是有类型的。也就是说要传递的行为必须是有类型的,这种类型就是函数接口。

除了传参之外,lambda表达式也可以出现在赋值符号的右边。

lambda表达式的语法: lambda表达式由参数、箭头、表达式组成。

(parameters) -> expression //此处行为为表达式,这里隐含了return语句。

或者

(parameters) -> { statements; } //此处行为为语句,需要返回时要手写return语句。

1,如果代码无法在一个表达式中完成,可以像写方法一样把代码放在大括号中。只有一行代码的Lambda表达式也可以使用大括号。

()->{

...

}

2,没有参数时,也要提供一个空的小括号。如果只有一个参数,而且这个参数的类型可以推导,也可以省略小括号。Lambda表达式也可以包含多个参数

(param)->expression

param->expression

3,大部分情况中,无需指定lambda表达式的返回类型。具体的返回类型可以由上下文推断得出。

这种类型推导实际上是Java7中的目标类型推断的扩展。在Java7中以下代码是合法的,这是泛型的又一个升级。

Map map=new HashMap<>(); //不用声明HashMap的中的键值对类型,系统可以通过Map的相关类型推断出来。

这就是所谓的类型推断。

4,lambda表达式中只在某些分支返回值,另一个些分支不返回值是不合法的。

5,与JavaScript相同,lambda表达式只有一个入参时,可以省略小括号。

example:

BinaryOperator add=(x,y)->x+y; //创建一个函数,用来计算x和y相加的结果。

注意:add不是两个数字的和,而是将两个数字加相的那行代码。

System.out.println(add.apply(1l,2l)); //打印3

解析:binaryOperator是一个接口,其含义进行一次两数据的某种操作,并返回这个操作的结果。其抽象方法来自父接口BiFunction。BiFunction接口是不同数据类型的操作、而binaryOperator接口是针对相同类型数据的操作。

public interface BiFunction {

R apply(T t, U u);

}

public interface BinaryOperator extends BiFunction{}

需要注意的是: Lambda表达式中引用的在表达式之外定义的局部变量必须是final或既成事实上的final变量。 这个约束性的规定来源于java 8之前的匿名内部类,java 8放宽了这个规定,既局部变量可以不加final关键字,但依然不能给该变量多次赋值。

函数接口

函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型。也就是说所谓的Lambda表达式对应的其实就是函数接口。 java8提供@FunctionalInterface注解函数接口,当然这个注解是非必须的,只要接口符合函数接口的标准(即只包含一个抽象方法的接口)即可。 函数式接口的抽象方法签名基本上就是Lambda表达式的签名,这种抽象方法叫作函数描述符。 几个重要的函数式接口,它们都位于java.util.function包中:

Predicate接口

@FunctionalInterface

public interface Predicate{

boolean test(T t);

}

Consumer接口

@FunctionalInterface

public interface Consumer{

void accept(T t);

}

BiConsumer接口

@FunctionalInterface

public interface BiConsumer {

void accept(T t, U u);

}

Function接口

@FunctionalInterfac

public interface Function{

R apply(T t);

}

为避免在使用原始类型时进行自动拆、装箱操作,jdk8提供了以上函数式接口的原始类型版本。

IntPredicate、DoublePredicate等

Supplier接口

@FunctionalInterface

public interface Supplier {

T get();

}

BinaryOperator接口

BinaryOprator接口继承自BiFunction接口,其接口方法源型如下:

R apply(T t, U u);

方法引用

方法引用是lambda表达式的一种简化写法。当要调用的方法是一个已经存在的方法时可以使用方法引用。使用方法引用替换整个Lambda表达式。 语法为:左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名(不带小括号)。

ObjectReference::methodName

一般方法的引用格式:

调用静态方法,ClassName::methodName。如 Person::compareByAge调用实例方法,Instance::methodName。如System.out::println;调用参数的实例方法,ClassName::methodName。Object::equals;调用构造方法,ClassName::new 。如:Person::new;注意:

当匿名方法有参数并且lambda表达式就是调用参数中的方法的时候,可以直接用参数的类名做为容器。如下:

List collected=Stream.of("a","b","hello")

.map(string->string.toUpperCase)

.collect(Collectors.toList());

//注意这里使用了方法引用

List collected=Stream.of("a","b","hello")

.map(String::toUpperCase)

.collect(Collectors.toList());

本质上讲:方法引用是Lambda表达式的快捷写法。当这个Lambda表达式代表的只是直接调用某个已经存在的方法时使用。

可以把方法引用当作针对仅涉及单一方法的Lambda的语法糖。

forExample:

public class LambdaExample {

public static void main(String[] args) {

List names = Arrays.asList("peter", "anna", "mike", "xenia");

/*匿名内部类的方式

Collections.sort(names, new Comparator() {

@Override

public int compare(String a, String b) {

return b.compareTo(a);

}

});

*/

/*lambda表达式

Collections.sort(names, (a,b) -> {

return b.compareTo(a);

});

*/

//简易写法

Collections.sort(names, (a, b) -> b.compareTo(a));

//进一步简写

Collections.sort(names,String::compareTo);

for(String s:names){

System.out.println(s);

}

}

}

public class ThreadExample {

public static void main(String[] args) {

Thread thread=new Thread(()->{

for(int i=0;i<10;i++){

System.out.println(i);

}

});

thread.start();

}

}

每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以你也可以给你的函数式接口添加默认方法。 我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加 @FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。

@FunctionalInterface

interface Converter {

T convert(F from);

}

Converter converter = (from) -> Integer.valueOf(from);

Integer converted = converter.convert("123");

System.out.println(converted); // 123

下一篇lambda2讲解具体的API语法,以及应用场景。

Java8中lambda表达式的语法,别人都会的,你还不会吗?「二」

变量不合法的表达式JAVA_Java8中lambda表达式的语法,别人都会的,你还不会吗?「一」...相关推荐

  1. python lambda表达式_Python中lambda表达式

    Python中lambda表达式 1.lambda的应⽤用场景 如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化. 2. lambda语法 lambda 参数列列表 : 表达式 ...

  2. Java8中Lambda表达式的10个例子

    Java8中Lambda表达式的10个例子  例1 用Lambda表达式实现Runnable接口 Java代码   //Before Java 8: new Thread(new Runnable() ...

  3. Python3中lambda表达式介绍

    Python3中的lambda表达式或lambda函数是匿名函数(anonymous function),意味着该函数没有名称.def关键字用于在Python3中创建一个普通函数,类似地,lambda ...

  4. Python中lambda表达式学习

    lambda只是一个表达式,函数体比def简单很多. lambda的主体是一个表达式,而不是一个代码块.仅仅能在lambda表达式中封装有限的逻辑进去. lambda表达式是起到一个函数速写的作用.允 ...

  5. c++中lambda表达式用法

    lambda表达式是C++11中引入的一项新技术,利用lambda表达式可以编写内嵌的匿名函数,用以替换独立函数或者函数对象,并且使代码更可读. 所谓函数对象,其实就是对operator()进行重载进 ...

  6. php有lambda表达式吗,Python中lambda表达式的简单介绍(附示例)

    本篇文章给大家带来的内容是关于Python中lambda表达式的简单介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一:匿名函数的定义 lambda parameter ...

  7. lambda函数if_Python3中lambda表达式与函数式编程讲解

    今天小编就为大家分享一篇关于Python3中lambda表达式与函数式编程讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧 简单来说,编程中提到的 lam ...

  8. python中lambda 表达式(无参数、一个参数、默认参数、可变参数(*args、**kwargs)、带判断的lambda、列表使用lambda)

    如果⼀个函数有⼀个返回值,并且只有⼀句代码,可以使⽤ lambda简化. lambda语法: lambda 参数列表 : 表达式 注意: lambda表达式的参数可有可⽆,函数的参数在lambda表达 ...

  9. Java中lambda表达式去重_JAVA8中Lambda和Stream

    Java8于2014年3月份发布,其主要更新的特性有:函数式接口.Lambda 表达式.集合的流式操作.注解的更新.安全性的增强.IO\NIO 的改进.完善的全球化功能等,本文将介绍Lambda表达式 ...

最新文章

  1. 准备IE--复习NP,NP从头开始,每天学一点,就多一点收获
  2. 东芝2505扫描软件_东芝P300机械硬盘上膛体验:内存大了,小姐姐再也不愁无处安放了...
  3. nyoj 677 碟战(最大流最小割定理)
  4. 【思维】最大降雨量(解题报告)
  5. 主体ubuntu16.04,宿体virtualbox下的windows7的共享文件夹设置
  6. Kickstart之添加自动化脚本
  7. 软件开发中需要专职的 QA 吗?
  8. mysql engine 和type_type=INNODB和engine=INNODB的区别
  9. CSS原理与CSS经验分享
  10. 企业信息化投入中咨询服务_嘉萱企业管理咨询服务 让发展中的企业真正实现全面性效益增长...
  11. Android抓包方法(二) 之Tcpdump命令+Wireshark
  12. 二十一天学通C++之异常概述
  13. Chromium OS?本土化气息的的Flint OS
  14. 谷歌邮箱lmap服务器填什么_Gmail/QQ邮箱/163邮箱等各大邮箱IMAP/SMTP/POP3地址
  15. 怎么把两个PDF合并成一个?这几种操作轻松合并
  16. 矩阵的转置与矩阵的逆
  17. Java8-惰性求值
  18. 去南阳旅游有什么纪念品可以买的?
  19. 数据库之关系数据库之超码,候选码,主码,主属性,非主属性(非码属性)之间的关系
  20. oracle 时间条件 当天,oracle 查询当天数据的sql条件写法

热门文章

  1. Spring JDK动态代理
  2. linux练习 串口跟进程6,linux下串口测试程序
  3. 【OpenCV 例程200篇】07. 图像的创建(np.zeros)
  4. android中svn插件安装,AndroidSDK安装SVN插件问题解决
  5. 三折线弹塑性滞回模型matlab,动力弹塑性滞回模型-迈达斯汇总.doc
  6. 抽象类可以用new创建对象吗_宠物可以用人类的湿巾吗?猫咪有泪痕可以用纸巾擦掉吗?...
  7. office另存为pdf的加载项_pdf怎么转换成word?打工人必备的丛林法则
  8. string 中的offset_【Java基础】String常量的长度有限制吗?
  9. java解析yml文件_如何基于JAVA读取yml配置文件指定key内容
  10. 【职场】高薪的条件你满足几条?