函数编程

购物车案例

创建下单商品类

/*** 下单商品信息对象*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Sku {//编号private Integer skuId;//名称private String skuName;//单价private Double skuPrice;//购买个数private Integer totalNum;//总价private Double totalPrice;//商品类型private Enum skuCategory;}

创建商品类型枚举

/*** 商品类型枚举类*/
@AllArgsConstructor
@NoArgsConstructor
public enum SkuCategoryEnum {CLOTHING(10,"服装类"),ELECTRONICS(20,"数码产品类"),SPORTS(30,"运动类"),BOOKS(40,"图书类");//商品类型编号private Integer code;//商品类型名称private String name;}

编写业务类

//构造商品信息
/*** 购物车服务类*/
public class CartService {/*** 加入到购物车的商品信息*/private static List<Sku> cartSkuList = new ArrayList<Sku>(){{add(new Sku(654032,"无人机",4999.00,1,4999.00,SkuCategoryEnum.ELECTRONICS));add(new Sku(642934,"VR一体机",2299.00,1,2999.00,SkuCategoryEnum.ELECTRONICS));add(new Sku(638482,"纯色衬衫",409.00,1,409.00,SkuCategoryEnum.CLOTHING));add(new Sku(621054,"跑步机",5999.00,1,5999.00,SkuCategoryEnum.SPORTS));add(new Sku(612350,"Java核心思想",129.00,1,129.00,SkuCategoryEnum.BOOKS));}};}

获得所有商品信息

/*** 返回商品信息列表* @return*/public static List<Sku> getCartSkuList (){return cartSkuList;}

需求一:找出购物车中所有的电子产品

  /*** Version 1.0.0* 找出购物车中所有的电子产品* @param cartSkuList* @return*/public static List<Sku> filterElectronicsSkus(List<Sku> cartSkuList){List<Sku> result = new ArrayList<Sku>();for (Sku sku:cartSkuList) {//若果商品类型等于电子产品类if (sku.getSkuCategory().equals(SkuCategoryEnum.ELECTRONICS)){result.add(sku);}}return result;}

测试一

public class Version1Test {@Testpublic void filterElectronicsSkus(){//获取所有商品列表List<Sku> cartSkuList = CartService.getCartSkuList();//查找电子类商品List<Sku> skus = CartService.filterElectronicsSkus(cartSkuList);System.out.println(JSON.toJSONString(skus,true));}
}

需求二:根据传入的商品类型查找商品信息

  /*** Version 2.0.0* 根据传入的商品类型查找商品信息* @return*/public static List<Sku> filterSkuByCategory(List<Sku> cartSkuList,SkuCategoryEnum skuCategoryEnum){List<Sku> result = new ArrayList<Sku>();for (Sku sku:cartSkuList) {if (skuCategoryEnum.equals(sku.getSkuCategory())){result.add(sku);}}return result;}

测试二

public class Version2Test {@Testpublic void filterSkuByCategory(){//查找购物车中图书类的商品集合List<Sku> cartSkuList = CartService.getCartSkuList();List<Sku> skus = CartService.filterSkuByCategory(cartSkuList, SkuCategoryEnum.BOOKS);System.out.println(JSON.toJSONString(skus,true));}
}

需求三:根据商品类型或商品总价来过滤商品类型

/*** Version 3.0.0* 根据商品类型或商品总价来过滤商品类型* @param cartSkuList* @param skuCategoryEnum* @param totalPrice* @param categoryOrPrice   true:商品类型  false:商品总价* @return*/public static List<Sku> filterSkus(List<Sku> cartSkuList,SkuCategoryEnum skuCategoryEnum,Double totalPrice,Boolean categoryOrPrice){List<Sku> skuList = new ArrayList<Sku>();for (Sku sku:cartSkuList) {//如果根据商品类型进行判断,sku类型与输入类型比较//如果根据商品总价进行判断,sku总价与输入总价比较if ((categoryOrPrice && skuCategoryEnum.equals(sku.getSkuCategory())) || (!categoryOrPrice && sku.getTotalPrice() > totalPrice)){skuList.add(sku);}}return skuList;}

测试三

public class Version3Test {@Testpublic void filterSkus(){//根据商品总价进行过滤List<Sku> cartSkuList = CartService.getCartSkuList();List<Sku> skus = CartService.filterSkus(cartSkuList, null, 5000.00, false);System.out.println(JSON.toJSONString(skus,true));}
}

需求四:对需求三进行改进

创建SkuPredicate接口

/*** Sku选择谓词接口*/
public interface SkuPredicate {/*** 选择判断标准* @param sku* @return*/boolean test(Sku sku);
}

业务方法

  /*** Version 4.0.0* 根据不同的Sku判断标准,对Sku列表进行过滤* @param cartSkuList* @param predicate - 不同的Sku判断标准策略* @return*/public static List<Sku> filterSkus(List<Sku> cartSkuList, SkuPredicate predicate){List<Sku> result = new ArrayList<Sku>();for (Sku sku:cartSkuList) {//根据不同的sku判断标准策略if (predicate.test(sku)){result.add(sku);}}return result;}

测试四

public class Version4Test {@Testpublic void filterSkus(){List<Sku> cartSkuList = CartService.getCartSkuList();//根据商品总价大于2000条件进行判断List<Sku> skus = CartService.filterSkus(cartSkuList, new SkuTotalPriceCategoryPredicate());System.out.println(JSON.toJSONString(skus,true));}
}

需求五:对需求四进行改进

创建SkuPredicate接口实现类

/*** 对Sku的商品类型为图书类的判断标准*/
public class SkuBooksCategoryPredicate implements SkuPredicate{@Overridepublic boolean test(Sku sku) {return SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory());}
}

创建SkuPredicate接口实现类

/*** 对Sku的商品总价是否超出2000为判断标准*/
public class SkuTotalPriceCategoryPredicate implements SkuPredicate{@Overridepublic boolean test(Sku sku) {return sku.getTotalPrice() > 2000;}
}

测试五:使用匿名内部类

public class Version5Test {@Testpublic void filterSkus(){List<Sku> cartSkuList = CartService.getCartSkuList();//根据商品总价大于2000条件进行判断List<Sku> skus = CartService.filterSkus(cartSkuList, new SkuPredicate() {@Overridepublic boolean test(Sku sku) {return sku.getTotalPrice() > 1000;}});System.out.println(JSON.toJSONString(skus,true));}
}

需求六:对需求五进行改进

创建SkuPredicate接口实现类

测试六:使用lambda表达式

public class Version6Test {@Testpublic void filterSkus(){List<Sku> cartSkuList = CartService.getCartSkuList();//根据商品总价大于2000条件进行判断List<Sku> skus = CartService.filterSkus(cartSkuList,(Sku sku)->sku.getTotalPrice() > 2000);System.out.println(JSON.toJSONString(skus,true));}
}

以上就是函数编程的演化历史,根据需求的不断变化。

Lambda 表达式简介

  • Java 8 引入函数式编程风格
  • 可以理解为一种匿名函数的代替
  • 通过行为参数化传递代码

Lambda 表达式的形式

  • (parameters )-> expression
  • (parameters )-> {statement;}

形式一:没有参数

()->System.out.println("Hello World");

形式二:只有一个参数

name->System.out.println("Hello World"+name);

形式三:没有参数,逻辑复杂

()->{System.out.println("Hello");System.out.println("World");}

形式四:包含两个参数方法

BinaryOperator<Long> functionAdd = (x,y) -> x+y;
Long result  = functionAdd.apply(1L,2L);

形式五:对参数显示声明

BinaryOperator<Long> functionAdd = (Long x,Long y) -> x+y;
Long result  = functionAdd.apply(1L,2L);

函数式接口

  • 接口中只有一个抽象方法
  • Java 8 的函数式接口朱注解: @FunctionInterface
  • 函数式接口的抽象方法签名:函数描述符

实战案例:自定义函数式接口
功能:实现读取本地文件后自定义处理逻辑功能

定义函数式接口

/*** 文件处理函数式接口*/
@FunctionalInterface
public interface FileConsumer {/*** 函数式接口抽象方法,* @param fileContent  - 文件内容字符串*/void fileHandler(String fileContent);
}

宾编写业务类读取文件内容

/*** 文件服务类*/
public class FileService {/*** 通过 url 获取本地文件内容,调用函数式接口处理* @param url* @param fileConsumer*/public void fileHandle(String url,FileConsumer fileConsumer) throws IOException {//创建文件读取流BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(url)));//定义行变量和内容String line ;StringBuilder stringBuilder = new StringBuilder();while((line = bufferedReader.readLine()) != null){stringBuilder.append(line+"\n");}//调用函数式接口方法,将文件内容传递给lambda表达式,实现业务逻辑fileConsumer.fileHandler(stringBuilder.toString());}}

测试

public class FileServiceTest {@Testpublic void fileHandle() throws IOException {FileService fileService = new FileService();//通过lambda表达式打印文件容fileService.fileHandle("D:\\demo\\app\\src\\main\\java\\com\\ausware\\yaowenyu\\lambda\\file\\FileService.java",fileContent -> System.out.println(fileContent));}}

常用函数接口及使用

接口 参数 返回类型 描述
Predicate< T > T boolean 用于判别一个对象。比如求一个人是否为男性。也叫断定性接口
Consumer< T > T void 用于接收一个对象进行处理但没有返回。比如接收一个人并打印他的名字。也叫消费型接口
Suppler< T > None T 用提供一个对象。也叫供给型接口
Function<T,R> T R 转换一个对象为不同类型的对象。

方法引用


方法引用:调用特定方法的Lambda表达式的一种快捷写法,可以让你重复使用现有的方法定义,并像Lambda表达式一样传递他们

指向静态方法的方法引用

指向任意类型实例方法的方法引用

指向现有对象的实例方法的方法引用

剑指高效编程之函数编程相关推荐

  1. 剑指高效编程之工具类

    工具类 Google Guava 工具集简介 Guava工程包含了若干被Google的Java项目广泛依赖的核心库,例如∶集合.缓存﹑原生类型支持.并发库.通用注解.字符串处理.I/O等等. 所有这些 ...

  2. 牛客网剑指offer编程实践1-10题

    牛客网剑指offer编程实践1-10题 1.二维数组中的查找 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这 ...

  3. 剑指offer编程题(JAVA实现)——第35题:数组中的逆序对

    github https://github.com/JasonZhangCauc/JZOffer 剑指offer编程题(JAVA实现)--第35题:数组中的逆序对 题目描述 在数组中的两个数字,如果前 ...

  4. 剑指offer编程题(JAVA实现)——第38题:二叉树的深度

    github https://github.com/JasonZhangCauc/JZOffer 剑指offer编程题(JAVA实现)--第38题:二叉树的深度 题目描述 输入一棵二叉树,求该树的深度 ...

  5. 牛客网 c++ 剑指Offer_编程题 第五题用两个栈实现队列

    前言: 牛客网 c++ 剑指Offer_编程题 第五题用两个栈实现队列 题目: **这个题目不难,但是我感觉题目出得奇怪,刚开始没理解要干啥 我一个队列就能实现他要的功能为啥要两个 队列 queue ...

  6. 2020-8-26 剑指offer编程小哥令狐 075211

    剑指offer~编程小哥令狐 一.数组类~ 03.数组中重复的数字 class Solution{public void swap(int[] nums,int i,int j){int temp=n ...

  7. 剑指Offer——编程题的Java实现(更新完毕……)

    目录 二维数组中的查找 替换空格 从尾到头打印链表 重建二叉树 用两个栈实现队列 用两个队列实现一个栈 旋转数组的最小数字 斐波那契数列 跳台阶 变态跳台阶 矩形覆盖 二进制中1的个数 数值的整数次方 ...

  8. 三天刷完《剑指OFFER编程题》--Java版本实现(第三天)

    正在更新中......... 剑指offer --Python版本的实现: 剑指offer(1/3)第一大部分 剑指offer(2/3)第二大部分 剑指offer(3/3)第三大部分 -------- ...

  9. 剑指Offer——编程题的Java实现

    声明:我写这个的意图是我在看书的过程中,就我掌握的内容做一个笔记,没有抄袭的意图.再次说明一下,我找工作的过程中并不顺利,没有像那些牛人们拿到一大把的Offer,我只是希望通过我自己的努力,不断提高自 ...

最新文章

  1. 8. String to Integer
  2. 有关Non-cacheable,,Cacheable, non-shareable,inner-shareable,outer-shareable的理解
  3. py---------面向对象进阶
  4. 字符串的压缩【百度】
  5. ThinikPHP 前端URL模式
  6. 毕业两年的我--奋斗中的程序员
  7. ubuntu下安装psycopg2报错
  8. 右侧快速入口滑动时左侧跟着变化
  9. 5-4卷积神经网(上)5-5卷积神经网(下)
  10. 图片上传下载连接云服务器tomcat
  11. 计算机txt公式,完整word版本积分公式
  12. 快手火山美拍秒拍抖音映客yy小影视频批量下载毛驴保存去水印助手
  13. Photoshop定义画笔选区为空的原因
  14. Coverage [minx,miny,maxx,maxy] is [12, 4, 13, 6, 3], index [x,y,z] is [2, 5, 3]错误原因及其解决方式...
  15. 自定义View的OnMeasure问题
  16. 两个苹果手机共享步数_两个苹果手机同一个id数据是否共享?
  17. android12.0(S) Launcher3 导入 AndroidStudio 调试编译
  18. 多旋翼无人机仿真 rotors_simulator:roll pitch yawrate thrust 控制器
  19. python基础语法测评_Python基础语法测评(A1卷)
  20. html5 无障碍插件,HTML5 无障碍测试 Chromium 核心的 Edge 以满分砌低 Chrome!

热门文章

  1. TSC 打印机开发TSPL黑底白字的打印以及一些问题
  2. DailyTask-changeLog学习手册
  3. Zrlog开源博客网站 安装教程
  4. 谷歌提出MaskGIT:掩码生成图像Transformer
  5. STM32的一个通用定时器理论上可以当做N个来用
  6. win10笔记本右键磁盘无响应,鼠标一直转圈圈,或卡死
  7. Android studio 出现一直在同步Syncing only active variant
  8. java按键音效,按下按钮停止声音循环
  9. nginx + uwsgi 搭建PYHTON web应用
  10. Axure8.0基础教程 一