菜鸡的Java笔记 第三十六 - java 函数式编程
StudyLambda
Lambda 指的是函数式编程,现在最为流行的编程模式为面向对象,很多的开发者并不认可面向对象,所以很多的开发者宁愿继续使用 C 语言进行开发,也不愿意使用java,c++
但是随着整个行业的技术发展,函数编程语言已经开始被很多的人所认可,于是java也是被迫环境因素追加了 Lambda
如果要想去理解 Lambda 表达式设置的背景,就需要首先理解匿名内部类
匿名内部类解决的问题:对于抽象类或接口的子类如果发现其只使用一次,那么就没有必要将其定义为一个类,这样可以节约类的定义空间,但是匿名内部类太麻烦了
范例:观察匿名内部类
package cn.mysterious;
interface IMessage{
public String getMsg(); } public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IMessage msg = new IMessage() { @Override
public String getMsg() {
// TODO Auto-generated method stub
return "ssssssssssssssss";
}
};
System.out.println(msg.getMsg());
} }
因为面向对象的最大特征:结构要完整,这个时候如果使用 Lambda 表达式呢?
package cn.mysterious;
interface IMessage{
public String getMsg(); } public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IMessage msg = () ->"?????????";
System.out.println(msg.getMsg());
}
}
一个简单的一行语句就代替了完整的结构,那么自然会有许多的追捧者去使用它
实际上 Lambda 表达式以上的做法只是其中的一种形式,它有三种语法:
() ->{多行语句,return 语句};
() ->单行语句;
() ->返回结果;
范例:多行语句定义
package cn.mysterious;
interface IMessage{
public String getMsg(); } public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IMessage msg = () ->{
String str = "???????";
return str;
};
System.out.println(msg.getMsg());
} }
如果现在设计的接口里面没有返回值的存在,那么方法体也可以使用一行语句,可以直接避免“{}”定义
package cn.mysterious;
interface IMessage{
public void print(); } public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IMessage msg = () -> System.out.println("???????????");;
msg.print();
} }
如果要想使用 Lambda 表达式有一个重要的前提:一个接口之中只允许有一个抽象方法,如果你现在需要强制描述接口定义(某一个接口就是函数式编程接口)则可以追加一个注解
package cn.mysterious;
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IMessage{
public void print(); }
public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IMessage msg = () -> System.out.println("???????????");;
msg.print();
} }
Lambda 是基于函数式接口定义的,如果要想使用 Lambda 重要的前提:一个接口之中只允许有一个抽象方法
如果有很多抽象方法呢?
package cn.mysterious;
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IMessage{
public void print();
public default void fun(){} }
public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IMessage msg = () -> System.out.println("???????????");;
msg.print();
msg.fun();
} }
*/
/*
在之前所学习的都属于对象的引用,对象引用的本质在于:同一块堆内存空间,可以被不同的栈内存所指向
那么方法的引用指的是一个方法可以设置不同的别名,即:可以被不同的接口的对象所使用
对于方法的引用在java里面提供有四种处理形式:
引用类中的静态方法:类名称 :: static 方法名称
引用某个对象的方法;实例化对象 :: 普通方法
引用某个特定的方法:类名称 :: 普通方法
引用构造方法:类名称 :: 普通方法
范例:引用静态方法
String 类有一个 valueOf() 方法,该方法可以将接收到的基本数据类型变为字符串
方法定义: public static String valueOf(数据类型 变量);
package cn.mysterious;
/**
* 进行以函数式接口定义
* @author mldn
* @param <P> 引用方法的参数类型
* @param <R> 引用方法的返回值定义
*/
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtile<P,R>{
public R convert(P p); // 做新的方法 }
public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IUtile<Integer,String> objA = String :: valueOf; // 方法引用
System.out.println(objA.convert(100));
} }
也可以使用 Integer,parseInt() 转换
package cn.mysterious;
public class Lang0 { public static void main(String[] args) {
// TODO Auto-generated method stub
IUtil<Integer,String> objA = String :: valueOf; // 方法引用
System.out.println(fun(objA,100).length());
}
public static <P,R> R fun(IUtil<P,R> temp,P p){
return temp.convert(p);
} }
/**
* 进行以函数式接口定义
* @author mldn
* @param <P> 引用方法的参数类型
* @param <R> 引用方法的返回值定义
*/
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<P,R>{
public R convert(P p); // 做新的方法 }
以上只是引用了一个简单的 static 方法,也可以直接引用某一个类中的方法
范例:引用 String 类中的字符串转大写方法
[“字符串”.toUpperCase] public String toUpperCase();
package cn.mysterious; @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<R>{
public R upper(); // 做新的方法 }
public class Lang0 { public static void main(String[] args) {
IUtil<String> obj = "hello" :: toUpperCase;
System.out.println(obj.upper());
}
}
范例:引用类中的普通方法
String 类有一个 compareTo() 方法,这个方法是一个普通方法,而且需要两个参数比较
方法: public int compareTo(String str);
package cn.mysterious; @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<R,P>{
public R compare(P p1,P p2); // 做新的方法 }
public class Lang0 { public static void main(String[] args) {
IUtil<Integer,String> obj = String :: compareTo;
System.out.println(obj.compare("A","a"));
}
}
以上使用的都是类的结构,而整个设计里面最大的亮点在于构造方法也可以设置别名引用
范例:引用构造方法
package cn.mysterious;
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<R,FP,SP>{
public R create(FP p1,SP p2); // 做新的方法 }
public class Lang0 { public static void main(String[] args) {
IUtil<Member,String,Integer> obj = Member :: new; // 引用构造
System.out.println(obj.create("????",20));
} }
class Member{
private String name;
private int age;
public Member(String name,int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Member [name=" + name + ", age=" + age + "]";
}
}
Lambda 表达式的操作除了可以自定义方法体之外,用户也可以去引用已经实现好的类中的方法
内建函数式接口
函数式接口是 Lambda 实现关键所在,但是很多时候如果要想进行一个项目设计的时候,肯定需要许多标准的函数式接口
所以在java设计过程之中考虑到用户使用标准型问题,所以也提供有四个内建的函数式接口
功能性函数接口: public Interface Function<T,R>{R apply(T t)}
消费型函数接口: public interface Consumer<T>{public void accept(T t)}
供给性函数接口: public interface Supplier<T>{public T get()}
断言型函数接口: public interface Predicate<T>{public boolean test(T t)}
范例:使用功能型接口
package cn.mysterious;
import java.util.function.Function;
public class Lang0 {
public static void main(String[] args) {
Function<Integer,String> obj = String :: valueOf;
System.out.println(obj.apply(100));
}
}
实际上在 java.util.function 开发包里面有许多扩展的函数式接口,可以帮助用户简化定义
范例:使用 IntFunction
package cn.mysterious;
import java.util.function.IntFunction;
public class Lang0 {
public static void main(String[] args) {
IntFunction<String> obj = String :: valueOf;
System.out.println(obj.apply(100));
}
}
范例:消费型接口,现在学习到的消费处理只有一个方法:打印输出
package cn.mysterious;
import java.util.function.Consumer;
import java.util.function.IntFunction;
public class Lang0 {
public static void main(String[] args) {
Consumer<String> obj = System.out :: println;
obj.accept("?????");
}
}
范例:供给型,字符串转大写或小写(“Hello” .toLowerCase())
package cn.mysterious;
import java.util.function.Supplier;
public class Lang0 {
public static void main(String[] args) {
Supplier<String> obj = "Hello" :: toLowerCase;
System.out.println(obj.get());
}
}
范例:断言型接口( startsWith() 方法,返回boolean,接收一个字符串)
package cn.mysterious;
import java.util.function.Predicate;
public class Lang0 {
public static void main(String[] args) {
Predicate<String> obj = "##hello" :: startsWith;
System.out.println(obj.test("##"));
}
}
如果不去考虑标准,这些接口完全可以自己来实现,而这四个接口是 java 中进行 Lambda 编程时所采用的标准接口
菜鸡的Java笔记 第三十六 - java 函数式编程的更多相关文章
- 菜鸡的Java笔记 第三十二 - java 静态导入的实现
静态导入的实现 为了理解静态导入的操作产生的动机,下面通过一个具体的代码来观察 范例:现在有一个 Import 的类,这个类中的方法全部都是 static 方法 packa ...
- Java从零开始学三十六(JAVA IO- 字符流)
一.字符流 BufferedReader:BufferedReader是从缓冲区之中读取内容,所有的输入的字节数据都将放在缓冲区之中 BufferedWriter:把一批数据写入到缓冲区,当缓冲区区的 ...
- Java开发学习(三十六)----SpringBoot三种配置文件解析
一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...
- “全栈2019”Java多线程第三十六章:如何设置线程的等待截止时间
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 下一章 "全栈2019"J ...
- 菜鸡的Java笔记 第三十四 Annotation
Annotation 多例模式特点: 1. 多例类可以有多个实例 2. 多例类必须自己创建自己的实例,并管理自己的实例,和向外界提供自己的实例 ...
- 菜鸡的Java笔记 第三十 - java 异常的捕获及处理
异常的捕获及处理 1.异常的产生分析以及所带来的影响 2.异常的处理的基本格式 3.异常的处理流程 4.异常的处理模式 5.自定义 ...
- 菜鸡的Java笔记 第三十五 接口定义增强
接口定义增强 在java从一开始到现在接口之中的核心组成部分:抽象方法与全局常量,但是随着技术的不断发展,用户在使用过程之中发现了有一些问题 如果说现在有一个接口经过了长年 ...
- Java开发笔记(三十六)字符串的常用方法
不管是给字符串赋值,还是对字符串格式化,都属于往字符串填充内容,一旦内容填充完毕,则需开展进一步的处理.譬如一段Word文本,常见的加工操作就有查找.替换.追加.截取等等,按照字符串的处理结果异同,可 ...
- Java从零开始学三十八(JAVA IO- 重定向IO)
一.三个静态变量 java.lang.System提供了三个静态变量 System.in(默认键盘) System.out(默认显示器) System.err 二.重写向方法 System提供了三个重 ...
随机推荐
- farOs 介绍
nGame nGame 一款文字游戏服务端框架;用于快速构建:自由探索.武侠.修真.模拟,回合制,剧本杀.动态语言小说.等服务器 如果你有期望实现的功能请加Q群 ngame计划 完善框架功能 farO ...
- 网络基础--简单理解什么是DNS? TCP? UDP? Http? Socket?
什么是IP 协议? 协议就是为了实现网络通信而创建的一系列规范. 通常我们的网络模型从上到下共分为4层: 应用层, 传输层, 网络层 和数据链路层. IP协议属于网络层协议,它精确定义了网络通信中 ...
- 洛谷 P7541 DOBRA 题解
hhh... 我又来写题解了 solution 题意简化 一个字符串,将所有的 _ 替换成大写字母,使结果字符串符合要求: 1.不包含三个连续 元音 或 辅音 字母: 2.字符串中至少有一个 L . ...
- HTTP基础系列之:一文搞懂URL
一般我们日常在上网的时候,会在浏览器的地址栏里输入一个网站的 "网址",点击下回车,就会跳到你想去的网站,就类似这样 但其实,叫做 "网址" 并不是特别的准确, ...
- 地形鞍部的提取(ArcPy实现)
1.背景 相邻两山头之间呈马鞍形的低凹部分称为鞍部.鞍部点是重要的地形控制点,它和山顶点.山谷点及山脊线.山谷线等构成地形特征点线,对地形具有很强的控制作用.因此,因此,对这些地形特征点.线的分析研究 ...
- wqs二分 学习笔记
wqs二分学习笔记 wqs二分适用题目及理论分析 wqs二分可以用来解决这类题目: 给你一个强制要求,例如必须\(n\)条白边,或者划分成\(n\)段之类的,然后让你求出最大(小)值.但是需要满足图像 ...
- Coursera Deep Learning笔记 序列模型(一)循环序列模型[RNN GRU LSTM]
参考1 参考2 参考3 1. 为什么选择序列模型 序列模型能够应用在许多领域,例如: 语音识别 音乐发生器 情感分类 DNA序列分析 机器翻译 视频动作识别 命名实体识别 这些序列模型都可以称作使用标 ...
- 计算机网络:HTTP
计算机网络基础:HTTP 先验知识 HTTP和其他协议的关系 通过下图,了解IP协议,TCP协议,DNS服务在使用HTTP协议通信过程中各自发挥的作用: 服务器处理流程 接受客户端连接 ------& ...
- “妈妈再也不用担心我忘交作业了!”——记2020BUAA软工团队项目选择
写在前面 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 团队项目选择 项目简介 项目名称:北航学生资源整合和作业提醒平台 项目内容: 设计实现一 ...
- mysqld_exporter监控mysql信息
mysqld_exporter监控mysql信息 一.背景 二.prometheus接入mysqld_exporter 1.安装mysqld_exporter 2.创建mysqld_exporter用 ...