编程语言的整个目的就在于操作值,要是按照历史上编程语言的传统,这些值被成为一等值,而编程语言中的其他结构也许有助于表示值的结构,但在程序执行期间不能传递,因此为二等值,比如方法和类等则是二等值,类可以实例化来产生值,但方法和类本身都不是值,java8的设计者则决定允许方法作为值,让编程更轻松.

举个栗子

就农场库存程序而言,如果要实现一个从列表中塞选出绿色苹果的功能,可能会这样写(1.0)

  1. public static List<Apple> filterGreenApples(List<Apple> inventory) {
  2. List<Apple> result = new ArrayList<>();
  3. for (Apple apple : inventory) {
  4. if ("green".equals(apple.getColor())){
  5. result.add(apple);
  6. }
  7. }
  8. return result;
  9. }

假如这个时候要赛选出不仅是绿色的苹果,可能会加入一个颜色作为参数,就象这样(2.0)

  1. public static List<Apple> filterGreenApples(List<Apple> inventory, String color) {
  2. List<Apple> result = new ArrayList<>();
  3. for (Apple apple : inventory) {
  4. if (color.equals(apple.getColor())){
  5. result.add(apple);
  6. }
  7. }
  8. return result;
  9. }

但这个时候别人可能还想区分出重苹果和轻苹果,你可能会这样来赛选重苹果

  1. public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight){
  2. List<Apple> result = new ArrayList<>();
  3. for (Apple apple : inventory){
  4. if (apple.getWeight() > weight) {
  5. result.add(apple);
  6. }
  7. }
  8. return result;
  9. }

这样解决确实不错,但是却复制了大量的代码来实现功能,它打破了DRY(Don't Repeat Yourself)的软件工程原则,会许这时候你可能会将两种条件结合起来,并用一个标识表示赛选那种类型的苹果,像这样(3.0)

  1. public static List<Apple> filterGreenApples(List<Apple> inventory, String color, Integer weight, boolean flag){
  2. List<Apple> result = new ArrayList<>();
  3. for (Apple apple : inventory){
  4. if ((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)) {
  5. result.add(apple);
  6. }
  7. }
  8. return result;
  9. }

但是,这并不是一个可行的解决方案,首先别人阅读你的代码的时候,true|false表示什么?如果这个时候还有更加复杂的塞选情况又该怎么办?java8的行为化参数可以解决这个问题

行为参数化

让方法接受多种行为(或战略)作为参数,并在内部使用,来完成不同的行为.

好处: 多种行为,一个参数,可以把迭代要塞选的集合的逻辑和对集合中每个元素应用的行为区分开来,这样可以重复使用同一个方法,给他不同的行为达到不同的目的.

定义一个接口来对选择标准建模

  1. public interface ApplePredicate {
  2. boolean test (Apple apple);
  3. }

现在就可以为它进行多个实现了,比如

  1. public class AppleGreenColorPredicate implements ApplePredicate {
  2. @Override
  3. public boolean test(Apple apple) {
  4. //仅选出绿色的苹果
  5. return "green".equals(apple.getColor());
  6. }
  7. }
  8. public class AppleHeavyWeightPredicate implements ApplePredicate {
  9. @Override
  10. public boolean test(Apple apple) {
  11. //仅选出重的苹果
  12. return apple.getWeight() > 150;
  13. }
  14. }

现在经过java8的改良,代码可能会是这个样子(4.0)

  1. public static List<Apple> filterApples(List<Apple> apples, ApplePredicate predicate){
  2. List<Apple> result = new ArrayList<>();
  3. for (Apple apple : apples){
  4. if (predicate.test(apple)){
  5. result.add(apple);
  6. }
  7. }
  8. return result;
  9. }

每次调用的时候,只需要传递相应的行为即可,比如

  1. List<Apple> greenApples = filterApples(inventory,new AppleGreenColorPredicate());

这样一来,每次塞选的是什么苹果完全取决于通过ApplePredicate对象传递的代码,换句话说,把filterApple的方法行为参数化了

当然,到了这里你可能还觉得不甘心,因为每次都要去创建一个新的类,有点啰嗦,所以,你可以使用匿名类来完成这一工作(5.0)

  1. List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
  2. @Override
  3. public boolean test(Apple apple) {
  4. return "red".equals(apple.getColor());
  5. }
  6. });

但是,匿名类还是不够还,因为它占用了很多空间,所以,在java8中可以直接使用Lambda表达式来完成(6.0)

  1. List<Apple> weightApples = filterApples(inventory, (Apple apple) -> apple.getWeight() > 150);

到目前为止,总算是可以解决啰嗦麻烦的问题了,因为它更像在描述问题本身.现在你可以将List抽象画,让他应用面更加广泛

  1. public interface Predicate<T>{
  2. boolean test(T t);
  3. }
  4. public static <T> List<T> filter(List<T> list, Predicate<T> p){
  5. List<T> result = new ArrayList<>();
  6. for(T e : list){
  7. if(p.test(e)){
  8. result.add(e);
  9. }
  10. }
  11. return result;
  12. }

现在在灵活性和简洁性之间找到了平衡点,这是java8带来的便利.

Java8函数式编程学习笔记(初探)的更多相关文章

  1. python 函数式编程学习笔记

    函数基础 一个函数就是将一些语句集合在一起的部件,它们能够不止一次地在程序中运行.函数的主要作用: 最大化的代码重用和最小化代码冗余 流程的分解 一般地,函数讲的流程是:告诉你怎样去做某事,而不是让你 ...

  2. Python函数式编程学习笔记

    High order function map(f,Iterable),将f依次作用在Iterable的每个元素然后返回一个Iterator,再用list(map(f,Iterable))进行转换得到 ...

  3. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  4. Java8函数式编程探秘

    引子 将行为作为数据传递 怎样在一行代码里同时计算一个列表的和.最大值.最小值.平均值.元素个数.奇偶分组.指数.排序呢? 答案是思维反转!将行为作为数据传递. 文艺青年的代码如下所示: public ...

  5. Bash脚本编程学习笔记08:函数

    官方资料:Shell Functions (Bash Reference Manual) 简介 正如我们在<Bash脚本编程学习笔记06:条件结构体>中最后所说的,我们应该把一些可能反复执 ...

  6. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  7. 关于Java8函数式编程你需要了解的几点

    函数式编程与面向对象的设计方法在思路和手段上都各有千秋,在这里,我将简要介绍一下函数式编程与面向对象相比的一些特点和差异. 函数作为一等公民 在理解函数作为一等公民这句话时,让我们先来看一下一种非常常 ...

  8. Linux Shell编程学习笔记——目录(附笔记资源下载)

    LinuxShell编程学习笔记目录附笔记资源下载 目录(?)[-] 写在前面 第一部分 Shell基础编程 第二部分 Linux Shell高级编程技巧 资源下载 写在前面 最近花了些时间学习She ...

  9. DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

随机推荐

  1. 【Docker】性能测试监控平台搭建:InfluxDB+Grafana+Jmeter+cAdvisor

    前言 在做性能测试时,如果有一个性能测试结果实时展示的页面,可以极大的提高我们对系统性能表现的掌握程度,进而提高我们的测试效率.但是我们每次打开Jmeter都会有几个硕大的字提示别用GUI模式进行负载 ...

  2. 启动tomcat一闪而过问题调试并解决

    之前一直用myelise+tomcat启动项目很正常,今天在尝试用绿色版tomcat8时,点击startup.bat文件时,一闪而过,tomcat未正常启动,也无法看到错误信息.搜索网络查找到调试方法 ...

  3. delphi文件名获取方法

    取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一:   Function Extrac ...

  4. 雷林鹏分享:C# 属性(Property)

    C# 属性(Property) 属性(Property) 是类(class).结构(structure)和接口(interface)的命名(named)成员.类或结构中的成员变量或方法称为 域(Fie ...

  5. Confluence 6 使用 LDAP 授权连接一个内部目录 - 高级设置

    ted Groups 为嵌套组启用或禁用支持. 一些目录服务器能够允许你在一个组中定义另外一个组.在这种结构下的用户组称为用户组嵌套.嵌套组的配置能够让子用户组继承上级用户组的权限,是系统的权限配置变 ...

  6. 为tomcat指定jdk

    安装好jdk,不配置环境变量 windows平台 在catalina.bat文件和setclasspath.bat文件开头的空白处加上如下两句(指定JDK): \jre linux平台 在catali ...

  7. python-day54--前端之js-DOM对象

    一.DOM对象 1.什么是HTML  DOM HTML  Document Object Model(文档对象模型---标签) 2.功能:定义了访问(查找)和操作HTML文档的标准方法 3.HTML ...

  8. linux--多进程进行文件拷贝

    学习IO的时候,我们都曾经利用文件IO函数,标准IO函数都实现了对文件的拷贝, 对某一个文件进行拷贝时,我们可以考虑一下几种方式: a.单进程拷贝: 假设某一文件需要拷贝100字节,每一个时间片可以完 ...

  9. Linux文件删除,但是df之后磁盘空间没有释放

    Linux 磁盘空间总是报警,查到到大文件,删除之后,df看到磁盘空间并没有释放. 查找了下发现系统对rm进行了alias   ,因为Linux对删除操作没有回收站机制,对rm操作进行了自定义,对删除 ...

  10. iOS UI-常用控件

    #import "ViewController.h" @interface ViewController ()<UITextFieldDelegate> // 标题标签 ...