全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Java8深入学习系列(一)lambda表达式介绍

前言

最近在学习java8,所以接下来会给大家介绍一系列的Java8学习内容,那么让我们先从lambda表达式开始。

众所周知从java8出现以来lambda是最重要的特性之一,它可以让我们用简洁流畅的代码完成一个功能。 很长一段时间java被吐槽是冗余和缺乏函数式编程能力的语言,随着函数式编程的流行java8种也引入了 这种编程风格。在此之前我们都在写匿名内部类干这些事,但有时候这不是好的做法,本文中将介绍和使用lambda, 带你体验函数式编程的魔力。


什么是lambda?

lambda表达式是一段可以传递的代码,它的核心思想是将面向对象中的传递数据变成传递行为。 我们回顾一下在使用java8之前要做的事,之前我们编写一个线程时是这样的:

Runnable r = new Runnable() {
 @Override
 public void run() {
 System.out.println("do something."); 
 }
}

也有人会写一个类去实现Runnable接口,这样做没有问题,我们注意这个接口中只有一个run方法, 当把Runnable对象给Thread对象作为构造参数时创建一个线程,运行后将输出do something. 。 我们使用匿名内部类的方式实现了该方法。

这实际上是一个代码即数据的例子,在run方法中是线程要执行的一个任务,但上面的代码中任务内容已经被规定死了。 当我们有多个不同的任务时,需要重复编写如上代码。

设计匿名内部类的目的,就是为了方便 Java 程序员将代码作为数据传递。不过,匿名内部 类还是不够简便。 为了执行一个简单的任务逻辑,不得不加上 6 行冗繁的样板代码。那如果是lambda该怎么做?

Runnable r = () -> System.out.println("do something.");

嗯,这代码看起来很酷,你可以看到我们用()和->的方式完成了这件事,这是一个没有名字的函数,也没有人和参数,再简单不过了。 使用->将参数和实现逻辑分离,当运行这个线程的时候执行的是->之后的代码片段,且编译器帮助我们做了类型推导; 这个代码片段可以是用{}包含的一段逻辑。下面一起来学习一下lambda的语法。

基础语法

在lambda中我们遵循如下的表达式来编写:

expression = (variable) -> action
  • variable: 这是一个变量,一个占位符。像x,y,z,可以是多个变量。
  • action: 这里我称它为action, 这是我们实现的代码逻辑部分,它可以是一行代码也可以是一个代码片段

可以看到Java中lambda表达式的格式:参数、箭头、以及动作实现,当一个动作实现无法用一行代码完成,可以编写 一段代码用{}包裹起来。

lambda表达式可以包含多个参数,例如:

int sum = (x, y) -> x + y;

这时候我们应该思考这段代码不是之前的x和y数字相加,而是创建了一个函数,用来计算两个操作数的和。 后面用int类型进行接收,在lambda中为我们省略去了return。

函数式接口

函数式接口是只有一个方法的接口,用作lambda表达式的类型。前面写的例子就是一个函数式接口,来看看jdk中的Runnable源码

@FunctionalInterface
public interface Runnable {
 /**
 * When an object implementing interface <code>Runnable</code> is used
 * to create a thread, starting the thread causes the object's
 * <code>run</code> method to be called in that separately executing
 * thread.
 * <p>
 * The general contract of the method <code>run</code> is that it may
 * take any action whatsoever.
 *
 * @see java.lang.Thread#run()
 */
 public abstract void run();
}

这里只有一个抽象方法run,实际上你不写public abstract也是可以的,在接口中定义的方法都是public abstract的。 同时也使用注解@FunctionalInterface告诉编译器这是一个函数式接口,当然你不这么写也可以,标识后明确了这个函数中 只有一个抽象方法,当你尝试在接口中编写多个方法的时候编译器将不允许这么干。

尝试函数式接口

我们来编写一个函数式接口,输入一个年龄,判断这个人是否是|成人|。

public class FunctionInterfaceDemo {
 @FunctionalInterface
 interface Predicate<T> {
 boolean test(T t);
 }
 /**
 * 执行Predicate判断
 *
 * @param age 年龄
 * @param predicate Predicate函数式接口
 * @return  返回布尔类型结果
 */
 public static boolean doPredicate(int age, Predicate<Integer> predicate) {
 return predicate.test(age);
 }
 
 public static void main(String[] args) {
 boolean isAdult = doPredicate(20, x -> x >= 18);
 System.out.println(isAdult);
 }
}

从这个例子我们很轻松的完成 是否是|成人| 的动作,其次判断是否是|成人|,在此之前我们的做法一般是编写一个 判断是否是|成人|的方法,是无法将 判断 共用的。而在本例只,你要做的是将 行为 (判断是否是|成人|,或者是判断是否大于30岁) 传递进去,函数式接口告诉你结果是什么。

实际上诸如上述例子中的接口,伟大的jdk设计者为我们准备了java.util.function包


我们前面写的Predicate函数式接口也是JDK种的一个实现,他们大致分为以下几类:

接口 参数 返回值 类别 示例
Consumer T void 消费型接口 输出一个值
Supplier None T 供给型接口 工厂方法
Function T R 函数型接口 获得 Artist 对象的名字
Predicate T boolean 断言型接口 这张唱片已经发行了吗

消费型接口示例

public static void donation(Integer money, Consumer<Integer> consumer){
 consumer.accept(money); 
}
public static void main(String[] args) {
 donation(1000, money -> System.out.println("好心的麦乐迪为Blade捐赠了"+money+"元")) ;
}

供给型接口示例

public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
 List<Integer> resultList = new ArrayList<Integer>() ;
 for(int x=0;x<num;x++) 
  resultList.add(supplier.get());
 return resultList ;
}
public static void main(String[] args) {
 List<Integer> list = supply(10,() -> (int)(Math.random()*100));
 list.forEach(System.out::println);
}

函数型接口示例

转换字符串为Integer

public static Integer convert(String str, Function<String, Integer> function) {
 return function.apply(str);
}
public static void main(String[] args) {
 Integer value = convert("28", x -> Integer.parseInt(x));
}

断言型接口示例

筛选出只有2个字的水果

public static List<String> filter(List<String> fruit, Predicate<String> predicate){
 List<String> f = new ArrayList<>();
 for (String s : fruit) {
 if(predicate.test(s)){
  f.add(s);
 }
 }
 return f;
}
public static void main(String[] args) {
 List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴莲", "火龙果", "水蜜桃");
 List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
 System.out.println(newFruit);
}

默认方法

在Java语言中,一个接口中定义的方法必须由实现类提供实现。但是当接口中加入新的API时, 实现类按照约定也要修改实现,而Java8的API对现有接口也添加了很多方法,比如List接口中添加了sort方法。 如果按照之前的做法,那么所有的实现类都要实现sort方法,JDK的编写者们一定非常抓狂。

幸运的是我们使用了Java8,这一问题将得到很好的解决,在Java8种引入新的机制,支持在接口中声明方法同时提供实现。 这令人激动不已,你有两种方式完成 1.在接口内声明静态方法 2.指定一个默认方法。

我们来看看在JDK8中上述List接口添加方法的问题是如何解决的

default void sort(Comparator<? super E> c) {
 Object[] a = this.toArray();
 Arrays.sort(a, (Comparator) c);
 ListIterator<E> i = this.listIterator();
 for (Object e : a) {
 i.next();
 i.set((E) e);
 }
}

翻阅List接口的源码,其中加入一个默认方法default void sort(Comparator<? super E> c) 。 在返回值之前加入default关键字,有了这个方法我们可以直接调用sort方法进行排序。

List<Integer> list = Arrays.asList(2, 7, 3, 1, 8, 6, 4);
list.sort(Comparator.naturalOrder());
System.out.println(list);

Comparator.naturalOrder()是一个自然排序的实现,这里可以自定义排序方案。 你经常看到使用Java8操作集合的时候可以直接foreach的原因也是在Iterable接口中也新增了一个默认方法:forEach , 该方法功能和 for 循环类似,但是允许 用户使用一个Lambda表达式作为循环体。

在后面的章节中我们再次通过案例来展示函数式编程的魅力 :)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


# java8  # lambda表达式  # lambda  # java8的lambda表达式  # JAVALambda表达式与函数式接口详解  # 浅析Java8新特性Lambda表达式和函数式接口  # 一文带你掌握Java8中Lambda表达式 函数式接口及方法构造器数组的引用  # Java Lambda表达式和函数式接口实例分析  # lambda表达式与传统接口函数实现方式对比详解  # 多个  # 的是  # 是一个  # 只有一个  # 判断是否  # 这是  # 一个函数  # 让我们  # 在此  # 这是一个  # 要做  # 它可以  # 返回值  # 都是  # 这一  # 是在  # 也有  # 很好  # 去了  # 过了 


相关文章: 建站VPS能否同时实现高效与安全翻墙?  独立制作一个网站多少钱,建立网站需要花多少钱?  新网站制作渠道有哪些,跪求一个无线渠道比较强的小说网站,我要发表小说?  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  如何通过免费商城建站系统源码自定义网站主题与功能?  深圳网站制作平台,深圳市做网站好的公司有哪些?  制作网站外包平台,自动化接单网站有哪些?  陕西网站制作公司有哪些,陕西凌云电器有限公司官网?  如何选择最佳自助建站系统?快速指南解析优劣  再谈Python中的字符串与字符编码(推荐)  制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?  建设网站制作价格,怎样建立自己的公司网站?  如何配置FTP站点权限与安全设置?  建站主机与服务器功能差异如何区分?  官网建站费用明细查询_企业建站套餐价格及收费标准指南  香港服务器选型指南:免备案配置与高效建站方案解析  如何用PHP工具快速搭建高效网站?  潮流网站制作头像软件下载,适合母子的网名有哪些?  如何获取PHP WAP自助建站系统源码?  股票网站制作软件,网上股票怎么开户?  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  兔展官网 在线制作,怎样制作微信请帖?  百度网页制作网站有哪些,谁能告诉我百度网站是怎么联系?  Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递  建站中国官网:模板定制+SEO优化+建站流程一站式指南  php8.4新语法match怎么用_php8.4match表达式替代switch【方法】  c# 服务器GC和工作站GC的区别和设置  云南网站制作公司有哪些,云南最好的招聘网站是哪个?  济南网站建设制作公司,室内设计网站一般都有哪些功能?  *服务器网站为何频现安全漏洞?  制作表格网站有哪些,线上表格怎么弄?  定制建站模板如何实现SEO优化与智能系统配置?18字教程  如何基于云服务器快速搭建个人网站?  建站主机无法访问?如何排查域名与服务器问题  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  网站专业制作公司有哪些,做一个公司网站要多少钱?  做企业网站制作流程,企业网站制作基本流程有哪些?  宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?  利用JavaScript实现拖拽改变元素大小  制作宣传网站的软件,小红书可以宣传网站吗?  郑州企业网站制作公司,郑州招聘网站有哪些?  建站主机选择指南:服务器配置与SEO优化实战技巧  如何登录建站主机?访问步骤全解析  c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】  一键网站制作软件,义乌购一件代发流程?  如何用搬瓦工VPS快速搭建个人网站?  义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?  南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?  如何基于云服务器快速搭建网站及云盘系统?  大同网页,大同瑞慈医院官网? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。