Java基础篇(05):函数式编程概念和应用
一、函数式概念
函数式编程是一种结构化编程的范式,主要思想是把运算过程尽量写成系列嵌套的函数调用。函数编程的概念表述带有很抽象的感觉,可以基于案例看:
public class Function01 {
public static void main(String[] args) {
// 运算:(x+y)* c
int x1 = 2 ;
int y1 = 3 ;
int c1 = 4 ;
int sum1 = x1 + y1 ;
int res1 = sum1 * c1 ;
System.out.println("res1 = "+res1);
}
}
这里基于过程的方式做计算,上面的代码块着重在描述程序执行过程。
在看基于函数的方式解决方法:
public class Function02 {
public static void main(String[] args) {
// 函数式计算
System.out.println("func01 = "+func01(2,3,4));
}
private static int func01 (int x,int y,int c){
return (x+y)*c;
}
}
函数式编程的核心要素:传入参数,执行逻辑,返回值,也可以没有返回值。
函数式的编程风格侧重描述程序的执行逻辑,不是执行过程。
同上面计算过程相比,函数式编程也减少很多临时变量的创建,代码风格也变的简洁清楚。
二、函数与方法
在Java语言中有函数式编程风格,但是Java代码中没有函数的说法,而是称为:方法;
public class Function03 {
public static void main(String[] args) {
Func03 func03 = new Func03();
func03.add(2);
System.out.println(func03.res1);
}
}
class Func03 {
public int res1 = 0 ;
public void add (int a1){
this.res1 = a1 +1 ;
}
}
类定义引用数据类型,类实例化后的对象可以调用类内部的方法和数据,这是最直观的感觉。
但是方法又有静态和非静态的区别,静态方法属于类所有,类实例化前即可使用。
非静态方法可以访问类中的任何成员变量和方法,并且必须是类实例化后的对象才可以调用。
三、JDK函数基础
1、Lambda表达式
Lambda表达式也可称为闭包,是推动Java8发布的最重要新特性,允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
这里就很鲜明的对比Lambda表达式语法和传统用法。
public class Lambda01 {
interface LambdaOpera {
int operation(int a, int b);
}
public static void main(String[] args) {
LambdaOpera lambdaOpera = new LambdaOpera(){
@Override
public int operation(int a, int b) {
return a * b ;
}
};
System.out.println(lambdaOpera.operation(3,2));
LambdaOpera lambdaOpera01 = (int a, int b) -> a + b;
LambdaOpera lambdaOpera02 = (int a, int b) -> a - b;
System.out.println(lambdaOpera01.operation(3,2));
System.out.println(lambdaOpera02.operation(3,2));
}
}
在看一个直观的应用案例,基于Lambda的方式创建线程,可以使代码变的更加简洁紧凑:
public class Lambda02 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
System.out.println(i);
}
}
}).start();
// 对比 Lambda 方式
new Thread(() -> {
for (int i = 0; i < 2; i++) {
System.out.println(i);
}
}).start();
}
}
在看一下Runnable接口的结构:
FunctionalInterface标记在接口上,表示该接口是函数式接口,并且该接口只包含一个抽象方法,
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Lambda表达式本身可以理解为就是一个接口的实现过程,这里runnable就是完整的Lambda表达式声明:
public class Lambda04 {
public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println("run one...");
};
Thread thread = new Thread(runnable);
thread.start();
}
}
Lambda表达式最直观的作用就是使得代码变得异常简洁,并且可以作为参数传递。
2、函数式接口
Lambda表达式虽然有很多优点,但是使用的时候需要定义一些接口用来完成编码,这样又使得表达式又变得重量级,Java8自身已经提供几个常见的函数式接口。
- Function:输入一个参数,返回一个结果;
- Consumer:输入一个参数,不返回结果;
- BiFunction:输入两个参数,返回一个结果;
- BiConsumer:输入两个参数,不返回任何结果;
public class Lambda05 {
public static void main(String[] args) {
Function<Integer, Integer> function01 = x -> x * 2;
System.out.println(function01.apply(2));
BiFunction<Integer, Integer, Integer> function02 = (x, y) -> x * y;
System.out.println(function02.apply(2, 3));
Consumer<String> consumer01 = msg -> System.out.println("msg:"+msg);
consumer01.accept("hello");
BiConsumer<String,Integer> consumer02 = (msg,i)
-> System.out.println(msg+":"+i);
consumer02.accept("world",3);
}
}
如果面对更复杂的业务需求,可以自定义函数式接口去解决。
四、Optional类
1、Null判断
Optional类是Java函数式编程的应用,主要用来解决常见的空指针异常问题。
在Java编程的开发中,很多地方都能常见空指针异常的抛出,如果想避免这个问题就要加入很多判断:
public class Optional01 {
public static void main(String[] args) {
User user = new User(1,"hello") ;
if (user != null){
if (user.getName() != null){
System.out.println(user.getName());
}
}
}
}
为了确保程序不抛出空指针这种低级的错误,在程序中随处可以null的判断,代码显然冗余和繁杂。
2、Optional应用
基于Optional类创建的对象可能包含空值和null值,也同样会抛出对应的异常:
public class Optional02 {
public static void main(String[] args) {
// NoSuchElementException
Optional<User> optionalUser = Optional.empty();
optionalUser.get();
// NullPointerException
Optional<User> nullOpt = Optional.of(null);
nullOpt.get();
}
}
所以在不明确对象的具体情况下,使用ofNullable()方法:
public class Optional03 {
public static void main(String[] args) {
User user = new User(1,"say");
Optional<User> optionalUser = Optional.ofNullable(user);
if (optionalUser.isPresent()){
System.out.println(optionalUser.get().getName());
}
User user1 = null ;
User createUser = Optional.ofNullable(user1).orElse(createUser());
System.out.println(createUser.getName());
User user2 = null ;
Optional.ofNullable(user2).orElseThrow( ()
-> new RuntimeException());;
}
public static User createUser (){
return new User(2,"hello") ;
}
}
这样看下来Optional结合链式方法和Lambda表达式就很大程度上简化了应用的代码量:
public class Optional04 {
public static void main(String[] args) {
// 1、map转换方法
User user = new User(99, "Java");
// user = null ;
String name = Optional.ofNullable(user)
.map(u -> u.getName()).orElse("c++");
System.out.println(name);
// 2、过滤方法
Optional<User> optUser01 = Optional.ofNullable(user)
.filter(u -> u.getName() != null && u.getName().contains("c++"));
// NoSuchElementException
System.out.println(optUser01.get().getName());
}
}
Optional提供null处理的各种方法,可以简洁很多代码判断,但是在使用风格上和之前变化很大。
五、Stream流
如果Optional简化很多Null的判断,那Stream流的API则简化了很多集合的遍历判断,同样也是基于函数式编程。

上述为Stream接口继承关系如图,同样提供一些特定接口和较大的包装接口,通过源码查看,可以看到和函数编程也是密切相关。
public class Stream01 {
public static void main(String[] args) {
Stream<String> stream = Stream.of("hello", "java");
stream.forEach(str -> System.out.print(str+";"));
}
}
Stream与函数接口结合使用,函数接口又可以使用Lambda表达式进行简化代码。在Java8通过Stream可以大量简化集合使用的代码复杂度。
public class Stream02 {
public static void main(String[] args) {
// 1、转换Stream
List<String> list = Arrays.asList("java+;", "c++;", "net;");
list.stream();
// 2、forEach操作
list.stream().forEach(System.out::print);
// 3、map映射,输出 3,4
IntStream.rangeClosed(2,3).map(x->x+1).forEach(System.out::println);
// 4、filter过滤
list.stream().filter(str -> str.contains("+")).forEach(System.out::print);
// 5、distinct去重
Integer[] arr = new Integer[]{3, 1, 3, 1, 2,4};
Stream.of(arr).distinct().forEach(System.out::println);
// 6、sorted排序
Stream.of(arr).sorted().forEach(System.out::println);
// 7、collect转换
List<String> newList = list.stream().filter(str -> str.contains("+"))
.collect(Collectors.toList());
newList.stream().forEach(System.out::print);
}
}
在没有Stream相关API之前,对于集合的操作和遍历都会产生大量的代码,通过Stream相关API集合的函数式编程和Lambda表达式的风格,简化集合很多操作。
Java基础篇(05):函数式编程概念和应用的更多相关文章
- Java基础篇Socket网络编程中的应用实例
说到java网络通讯章节的内容,刚入门的学员可能会感到比较头疼,应为Socket通信中一定会伴随有IO流的操作,当然对IO流比较熟练的哥们会觉得这是比较好玩的一章,因为一切都在他们的掌握之中,这样操作 ...
- Java多线程系列--“基础篇”05之 线程等待与唤醒
概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...
- 小白—职场之Java基础篇
java基础篇 java基础 目录 1.java是一种什么语言,jdk,jre,jvm三者的区别 2.java 1.5之后的三大版本 3.java跨平台及其原理 4.java 语言的特点 5.什么是字 ...
- JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)
本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...
- java基础篇---I/O技术
java基础篇---I/O技术 对于任何程序设计语言而言,输入输出(I/O)系统都是比较复杂的而且还是比较核心的.在java.io.包中提供了相关的API. java中流的概念划分 流的方向: 输 ...
- Java基础教程:面向对象编程[1]
Java基础教程:面向对象编程 内容大纲 Java语言概述 Java语言特点 1.Java为纯面向对象的语言,它能够直接反映现实生活中的对象.总之,Everything is object! 2.平台 ...
- Java基础教程:面向对象编程[3]
Java基础教程:面向对象编程[3] 内容大纲 基础编程 获取用户输入 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入.我们可以查看Ja ...
- 045 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 07 for循环应用及局部变量作用范围
045 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 07 for循环应用及局部变量作用范围 本文知识点:for循环应用及局部变量作用范围 for循环 w ...
- iOS系列 基础篇 05 视图鼻祖 - UIView
iOS系列 基础篇 05 视图鼻祖 - UIView 目录: UIView“家族” 应用界面的构建层次 视图分类 最后 在Cocoa和Cocoa Touch框架中,“根”类时NSObject类.同样, ...
- 金三银四跳槽季,BAT美团滴滴java面试大纲(带答案版)之一:Java基础篇
Java基础篇: 题记:本系列文章,会尽量模拟面试现场对话情景, 用口语而非书面语 ,采用问答形式来展现.另外每一个问题都附上“延伸”,这部分内容是帮助小伙伴们更深的理解一些底层细节的补充,在面试中可 ...
随机推荐
- grpc是基于http/2协议的高性能的rpc框架
师傅领进门,修行在个人,跟着官方脚手架demo了grpc后,之后就需要扩展前后知识边界,下面总结grpc的前世今生和最佳实践. https://www.cnblogs.com/JulianHuang/ ...
- Android移动、缩放和旋转手势实现
Android的部分图片编辑应用中需要对图片进行移动.缩放和旋转,这些变化都依赖于触摸手势实现,而本文主要阐述移动.缩放和旋转手势的简单实现. 一.移动 首先需要从触摸事件(MotionEvent)中 ...
- Android开发之账号密码登录跳转、固定时间显示进度条实现
登陆界面.登陆跳转和进度条功能实现 首先打开Android studio新建一个空项目,打开layout文件夹下的activity_main.xml文件,来设置登陆界面的布局.登陆界面需要两个输入框, ...
- git blame 用法小记
1.概述 git管理的代码仓库,在协作开发中不可避免地会出现代码冲突,或者有新手错误地提交代码.出现问题不可怕,可怕的是找不到问题出在哪里.有时候找到出问题的代码,却不知道是谁提交的.git提供了一个 ...
- C#数据结构与算法系列(十三):递归——迷宫问题
1.示例 2.代码实现 public class Maze { public static void Test() { int[][] map = new int[8][]; for (int i = ...
- Spire.Cloud 在线协同编辑Word文档
协同编辑,即项目管理者在用户管理系统下,允许多人(用户)同时编辑同一Word/Excel/PPT 文档.Spire.Cloud支持的协同编辑模式包含两种: 1. 快速模式:其他编辑者可以及时看到对文档 ...
- 伯克利:serverless是下一代计算范式
摘要:Serverless技术正是云厂商的基于规模经济的一个选择. 引子 刚过去的HC2020,华为面向多样化算力的时代,发布了DC分布式计算的三个开发套件,其中一个是元戎组件.元戎是基于函数计算的分 ...
- GaussDB拿下的安全认证CC EAL4+究竟有多难?
摘要:近日,经过全球知名独立认证机构SGS Brightsight实验室的安全评估,华为云GaussDB企业级分布式数据库内核获得全球权威信息技术安全性评估标准CC EAL4+级别认证 本文分享自华为 ...
- 技术+案例详解无监督学习Autoencoder
摘要:本篇文章将分享无监督学习Autoencoder的原理知识,然后用MNIST手写数字案例进行对比实验及聚类分析. 本文分享自华为云社区<[Python人工智能] 十五.无监督学习Autoen ...
- 火山引擎A/B测试:MAB智能调优实验,企业活动效果提升新利器
618临近,各大电商APP的预热活动已然拉开序幕.对企业而言,一场活动从策划到上线,中间经过效果验证,其业务成本很高.一个好的活动创意从策划.开发.到最终发布,至少会经历几周实践,如果中间还经历A ...