一、Lambda 的延迟执行

  有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费。而Lambda表达式是延迟执行的,这正好可以
作为解决方案,提升性能 。

  性能浪费的日志案例

    注意:日志可以帮助我们快速的定位问题,记录程序运行过程中的情况,以便项目的监控和优化。
    一种典型的场景就是对参数进行有条件使用,例如对日志消息进行拼接后,在满足条件的情况下进行打印输出:

 public class DemoLogger {
private static void log(int level, String msg) {
if (level == 1) {
System.out.println(msg);
}
} public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
log(1, msgA + msgB + msgC);
}
}

  这段代码存在问题:无论级别是否满足要求,作为 log 方法的第二个参数,三个字符串一定会首先被拼接并传入方
法内,然后才会进行级别判断。如果级别不符合要求,那么字符串的拼接操作就白做了,存在性能浪费。

  Lambda 的更优写法
   使用Lambda 必然需要一个函数式接口:

 @FunctionalInterface
public interface MessageBuilder {
String buildMessage();
}

  然后对 log 方法进行改造

 public class Demo02LoggerLambda {
private static void log(int level, MessageBuilder builder) {
if (level == 1) {
System.out.println(builder.buildMessage());
}
} public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
log(1, () ‐ > msgA + msgB + msgC );
}
}

  这样一来,只有当级别满足要求的时候,才会进行三个字符串的拼接;否则三个字符串将不会进行拼接。

  证明Lambda 的延迟

  通过下面代码进行验证:

 public class DemoLoggerDelay {
private static void log(int level, MessageBuilder builder) {
if (level == 1) {
System.out.println(builder.buildMessage());
}
} public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
log(2, () ‐ > {
System.out.println("Lambda执行!");
return msgA + msgB + msgC;
});
}
}

  从结果中可以看出,在不符合级别要求的情况下,Lambda将不会执行。从而达到节省性能的效果。

  Tips:实际上使用内部类也可以达到同样的效果,只是将代码操作延迟到了另外一个对象当中通过调用方法来完成。而是否调用其所在方法是在条件判断之后才执行的。

二、使用Lambda 作为参数和返回值

    Java中的Lambda表达式可以被当作是匿名内部类的替代品。如果方法的参数是一个函数式接口类型,那么就可以使用Lambda表达式进行替代。

    使用Lambda表达式作为方法参数,其实就是使用函数式接口作为方法参数。

    例如 java.lang.Runnable 接口就是一个函数式接口,假设有一个 startThread 方法使用该接口作为参数,那么就可以使用Lambda进行传参。这种情况其 实和 Thread 类的构造方法参数为 Runnable 没有本质区别。

    Demo:

 public class DemoRunnable {
private static void startThread(Runnable task) {
new Thread(task).start();
} public static void main(String[] args) {
startThread(() ‐ > System.out.println("线程任务执行!"));
}
}

    类似地,如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式。

    当需要通过一个方法来获取一个 java.util.Comparator 接口类型的对象作为排序器时,就可以调该方法获取。

    Demo:

  import java.util.Arrays;
import java.util.Comparator; public class Demo06Comparator {
private static Comparator<String> newComparator() {
return (a,b) ‐>b.length() ‐a.length();
} public static void main(String[] args) {
String[] array = {"abc", "ab", "abcd"};
System.out.println(Arrays.toString(array));
Arrays.sort(array, newComparator());
System.out.println(Arrays.toString(array));
}
}

    其中直接 return 一个Lambda 表达式即可。

Java 之 函数式编程的更多相关文章

  1. paip. java的 函数式编程 大法

    paip. java的 函数式编程 大法 Java 语言中常被忽视的一个方面是它被归类为一种命令式(imperative)编程语言.命令式编程虽然由于与 Java 语言的关联而相当普及,但是并不是惟一 ...

  2. Java Stream函数式编程案例图文详解

    导读 作者计划把Java Stream写成一个系列的文章,本文只是其中一节.更多内容期待您关注我的号! 一.什么是Java Stream? Java Stream函数式编程接口最初是在Java 8中引 ...

  3. Java Stream函数式编程图文详解(二):管道数据处理

    一.Java Stream管道数据处理操作 在本号之前发布的文章<Java Stream函数式编程?用过都说好,案例图文详解送给你>中,笔者对Java Stream的介绍以及简单的使用方法 ...

  4. Java 8 函数式编程

    今天打开Oracle Java官网一看,Java已经更新到 13 了 https://www.oracle.com/technetwork/java/javase/jdk-relnotes-index ...

  5. Guava 教程(3):Java 的函数式编程,通过 Google Collections 过滤和调用

    原文出处: oschina 在本系列博客的第一.二部分,我介绍了非常优秀的Google Collections和Guava包.本篇博客中我们来看看如何使用Google Collections来做到过滤 ...

  6. Java Stream函数式编程第三篇:管道流结果处理

    一.Java Stream管道数据处理操作 在本号之前写过的文章中,曾经给大家介绍过 Java Stream管道流是用于简化集合类元素处理的java API.在使用的过程中分为三个阶段.在开始本文之前 ...

  7. Java 中函数式编程方法形参为基本类型和引用类型

    简单复习下 基本数据类型值传递 值传递,原变量的值不会被修改 private final Consumer sout = System.out::println; @Before public voi ...

  8. Java函数式编程原理以及应用

    一. 函数式编程 Java8所有的新特性基本基于函数式编程的思想,函数式编程的带来,给Java注入了新鲜的活力. 下面来近距离观察一下函数式编程的几个特点: 函数可以作为变量.参数.返回值和数据类型. ...

  9. Java 函数式编程(Lambda表达式)与Stream API

    1 函数式编程 函数式编程(Functional Programming)是编程范式的一种.最常见的编程范式是命令式编程(Impera Programming),比如面向过程.面向对象编程都属于命令式 ...

随机推荐

  1. Ubuntu 16.04与Win10双系统双硬盘安装图解

    一.先做准备工作.建议:在当前系统所在的硬盘上,留一片空的主分区安装Ubuntu系统. 2.划分多大的空间够?安装的过程中需要涉及到分区,为了以免日后重装,我的建议是如下分区:1).5G,主分区,空间 ...

  2. CgLib实现AOP

    一.CgLib实现动态代理的例子 1.创建Person类 package com.example.cglib; public class Person { public void study(){ S ...

  3. 【转】redis报错“max number of clients reached"

    查看redis监控的时候看到redis的graph出现不正常的情况,截图如下: 如上面截图所展示的样子,可以看到redis 的客户端连接数很突兀的上升到10K,又突然下降到0.排除了监控本身的原因,很 ...

  4. shell 数学计算的N个方法

    let使用方法 root@172-18-21-195:/tmp# n1=5 root@172-18-21-195:/tmp# n2=10 root@172-18-21-195:/tmp# let re ...

  5. [LeetCode] 121. Best Time to Buy and Sell Stock 买卖股票的最佳时间

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  6. [LeetCode] 533. Lonely Pixel II 孤独的像素 II

    Given a picture consisting of black and white pixels, and a positive integer N, find the number of b ...

  7. golang 基于channel封装资源池(可用于封装redis、mq连接池)

    package pool import ( "errors" "io" "sync" "time" ) var ( Er ...

  8. Java设计模式之:单例模式

    单例模式 建议实现方式:枚举方式实现单例 单例模式的定义 单例模式就是在程序运行中只实例化一次,创建一个全局唯一对象,有点像 Java 的静态变量,但是单例模式要优于静态变量,静态变量在程序启动的时候 ...

  9. Bat批处理之for/f详解

    转自:https://www.cnblogs.com/zhangq/p/3988697.html 含有/F的for格式: FOR /F ["options"] %%i IN (fi ...

  10. mysql查询之上升的温度,有趣的电影,超过5名学生的课,大国,反转性别, 换座位

    最近发现一个网站 力扣 查看 上面有很多算法和数据库的题目,做了一下,发现自己平时都疏忽了,因此边做边记录下来 1.上升的温度 给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天 ...