在一起来学Java8(二)——Lambda表达式中我们学习了Lambda表达式的基本用法,现在来了解下复合Lambda。

Lambda表达式的的书写离不开函数式接口,复合Lambda的意思是在使用Lambda表达式实现函数式接口抽象方法后,还可以再次调用接口的其它方法,因为从Java8开始,接口中可以包含默认实现的方法。关于接口默认实现方法将会在后面章节详细阐述。

常见的复合Lambda常见的有以下几类:

比较器复合,对应的函数式接口:Comparator

谓词复合,对应的函数式接口:Predicate

函数复合,对应的函数式接口:Function

比较器复合

先来看下Comparator接口的常见用法,针对商品价格从低到高排序

package learn.java8.ch4;

import java.util.Arrays;

import java.util.Comparator;

import java.util.List;

class Goods {

private String name;

private int price;

public Goods(String name, int price) {

super();

this.name = name;

this.price = price;

}

省略get set

}

public class ComparatorTest {

public static void main(String[] args) {

List list = Arrays.asList(

new Goods("mete30", 3999),

new Goods("mete30 pro", 4999),

new Goods("redmi k20", 2999),

new Goods("iqoo", 2999),

new Goods("iphone11", 5000)

);

Comparator comparatorForPrice = (Goods goods1, Goods goods2) -> {

return Integer.compare(goods1.getPrice(), goods2.getPrice());

};

list.sort(comparatorForPrice);

System.out.println(list);

}

}

这里是根据价格从低到高排序,我们可以再加一个需求,如果价格一样,再根据商品名称排序。那么代码可以这样写:

public static void main(String[] args) {

List list = Arrays.asList(new Goods("mete30", 3999), new Goods("mete30 pro", 4999),

new Goods("redmi k20", 2999), new Goods("iqoo", 2999), new Goods("iphone11", 5000));

Comparator comparatorForPrice = (Goods goods1, Goods goods2) -> {

return Integer.compare(goods1.getPrice(), goods2.getPrice());

};

Comparator comparatorForName = (Goods goods1, Goods goods2) -> {

return goods1.getName().compareTo(goods2.getName());

};

// 把两个函数式接口进行复合,组成一个新的接口

Comparator finalComparator = comparatorForPrice.thenComparing(comparatorForName);

list.sort(finalComparator);

System.out.println(list);

}

上面的例子中Comparator finalComparator = comparatorForPrice.thenComparing(comparatorForName);就是复合Lambda表达式的体现。其中thenComparing()方法是Comparator接口的一个默认实现方法。

谓词复合

谓词复合,即使用谓词函接口来实现,谓词接口定义如下:

@FunctionalInterface

public interface Predicate {

// 抽象接口,判断是否为真

boolean test(T t);

// 默认方法,跟另一个谓词一起判断

default Predicate and(Predicate super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) && other.test(t);

}

// 默认方法,判断后进行非操作

default Predicate negate() {

return (t) -> !test(t);

}

// 默认方法,跟另一个谓词一起判断

default Predicate or(Predicate super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) || other.test(t);

}

static Predicate isEqual(Object targetRef) {

return (null == targetRef)

? Objects::isNull

: object -> targetRef.equals(object);

}

}

下面来看下具体的例子:

package learn.java8.ch4;

import java.util.function.Predicate;

public class PredicateTest2 {

static class Goods {

private String name;

// 价格

private int price;

// 库存

private int storeCount;

public Goods(String name, int price, int storeCount) {

super();

this.name = name;

this.price = price;

this.storeCount = storeCount;

}

}

public static void main(String[] args) {

Goods mete30pro = new Goods("mete30 pro", 4999, 111);

Goods iphone11 = new Goods("iphone11", 5000, 444);

Predicate predicate = (goods) -> goods.price > 4000;

System.out.println("mete30pro价格是否大于4000:" + predicate.test(mete30pro));

Predicate predicatePrice = (goods) -> goods.price > 6000;

Predicate predicateStore = (goods) -> goods.storeCount > 400;

// 价格大于6000或库存大于400

Predicate predicateOr = predicatePrice.or(predicateStore);

System.out.println("价格大于6000或库存大于400:" + predicateOr.test(iphone11));

}

}

函数复合

函数复合使用java.util.function.Function函数式接口中来实现。

Function接口定义如下:

// 两个泛型参数,T表示入参类型,R表示返回类型

@FunctionalInterface

public interface Function {

// 抽象方法

R apply(T t);

// 默认实现方法,先执行before,将结果带入当前apply方法中执行

default Function compose(Function super V, ? extends T> before) {

Objects.requireNonNull(before);

return (V v) -> apply(before.apply(v));

}

// 按顺序执行,先执行当前apply函数,再执行指定的after.apply函数

default Function andThen(Function super R, ? extends V> after) {

Objects.requireNonNull(after);

return (T t) -> after.apply(apply(t));

}

// 辅助方法,始终返回入参值

static Function identity() {

return t -> t;

}

}

从代码上看很容易就能看懂,接下来列举几个简单例子,首先来看下andThen方法的使用:

private static void test1() {

Function funMultiply = (input) -> input * 2;

Function funMinus = (input) -> input - 1;

// input * 2 - 1

Function finalFun = funMultiply.andThen(funMinus);

Integer result = finalFun.apply(2);

System.out.println(result); // 3

}

这个例子中定义两个函数,一个对参数做乘法操作然后返回,一个对参数做减法操作然后返回。接着使用andThen方法把两个函数串联起来。用数学公式表示即为:2 * 2 - 1

接下来是compose例子:

private static void test2() {

Function funMultiply = (input) -> input * 2;

Function funMinus = (input) -> input - 1;

// (input - 1) * 2

Function finalFun = funMultiply.compose(funMinus);

Integer result = finalFun.apply(2);

System.out.println(result); // 2

}

这里是先执行减法,得到的结果传入,再执行乘法操作。用数学公式表示即为:(2 - 1) * 2

定期分享技术干货,一起学习,一起进步!

JAVA复合判断_一起来学Java8(四)——复合Lambda相关推荐

  1. 项目中使用 java函数式编程_函数式编程在Java8中使用Lambda表达式进行开发

    事情起因 如果不喜欢看故事的同学,请前往下一章节. 事情起因是我打算集成Redis缓存,配置了Redis以后,发现@Cacheable注解始终不生效,折腾了大半天以后,我的心态已经崩了,决定不使用@C ...

  2. java 简化判断_简化Java内存分析

    java 简化判断 作为一名典型的Java开发人员,除了遵循关闭连接,流等典型的最佳实践外,我从未监视过应用程序的内存使用情况.最近,我们在JBoss服务器中遇到了一些问题,不得不深入研究内存管理Ja ...

  3. 学java还是安卓_零基础学安卓好还是学java好

    零基础学安卓好还是学java好 关于Java的学习很多同学都有这样或者那样的疑问,比如我是自学Java好呢还是参加Java培训好呢?Java好学吗?安卓和java哪个难学等等.今天我们就先简单的来看两 ...

  4. java编程赋值运算符_跟我学java编程—简单赋值运算符“=”

    赋值运算符是双目运算符,用在赋值表达式中.赋值运算符将值存储在运算符左边操作数指定的变量中.有两种赋值操作,简单赋值和复合赋值,简单赋值把运算符右边的操作数的值存储在运算符左边操作数指定的变量中:复合 ...

  5. java 短路判断_细数Java最坑爹的10大功能点

    作者:践行精神自由 原文:https://www.sohu.com/a/357927861_115128 作为一门面向对象的编程语言,Java凭借其简单易用.功能强大的特点受到了广大编程爱好者的青睐, ...

  6. java 引用 判断_[JAVA基础]你知道Java的四种引用类型吗

    https://www.cnblogs.com/huajiezh/p/5835618.html https://www.cnblogs.com/yueshutong/p/9531347.html 在J ...

  7. java break语句_跟我学java编程—Java跳转语句—break语句

    有时可能不知道循环将要执行的次数,终止循环的条件可在以后确定,所以需要提供一种机制在条件满足的时候跳出循环.有时候,我们需要根据条件跳过循环中的一些语句.Java语言提供了break和continue ...

  8. java学习出师_零基础学java来这里 出师如此简单

    当今时代是互联网的时代,互联网时代的到来,使得我们的生活更加便利,同时互联网时代的到来也大大增加了市场对于技术人才的需求,在此时,Java编程语言的许多特性势使得它迅速成长,学习的人也越来越多 jav ...

  9. java 短路判断_随笔 | 奇淫技巧 | Java:记 return 和短路运算符的妙用

    在阅读 AtomicStampedReference 的源码中,在 compareAndSet() 方法发现一段代码: return expectedReference == current.refe ...

最新文章

  1. 《UX最佳实践:提高用户体验影响力的艺术 》一3.6 总结
  2. Django框架(上传Excel文件并读取)
  3. [数据库] MySQL基础知识之日期判断及添加排序序号
  4. 为什么Facebook的API以一个循环作为开头?
  5. 读取ppt并存入数据库_Java解析Excel文件并把数据存入数据库
  6. parquet格式_【存储】基于列存之Parquet格式
  7. Vue中基于Vuex使用echarts组件动态数据绑定的方法
  8. 一条能让 iPhone 崩溃的 app 通知信息
  9. LeetCode 724. Find Pivot Index
  10. 无线发射机中的正交上变频技术--USRP X410软件无线电平台开发
  11. Lambert 投影转换相关代码
  12. c语言编程基础实验结果与分析,C语言实验指导1--C语言编程基础.doc
  13. angularjs 动态监控数据
  14. 数据结构教程(第五版 李春葆 上机实验题3 验证性实验)
  15. Lumiprobe/艾美捷——LumiMAG基因组DNA血液和口腔试剂盒
  16. HTML5+CSS3-边框背景图、多背景图、CSS选择器、网络字体、边框背景图片、过渡、放大、旋转
  17. dialogfragment 数据交互_交互的学习与应用指南 | 人人都是产品经理
  18. [PCIe] linux 下测试ASPM
  19. NAR:人类虚拟代谢数据库——整理人类和肠道菌群与营养和疾病
  20. GDA 和logistic回归的联系

热门文章

  1. 代码结构中Dao,Service,Controller,Util,Model意思和划分
  2. linux扩容根目录空间_记一次生产线上Linux系统根目录爆满问题解决办法
  3. 面试官常考的 21 条 Linux 命令
  4. MySQL误删数据?快速恢复指南来了!
  5. 神奇的 SQL 之 HAVING → 容易被轻视的主角
  6. Java 3 年,25K 多吗?
  7. Java 中的异常处理
  8. Java受检异常和非受检异常
  9. Webstorm相关设置
  10. windows7.0旗舰版安装后控制面板自带的Microsoft程序