java代码(15) ---java8 Function 、Consumer 、Supplier
Java8 Function、Consumer、Supplier
有关JDK8新特性之前还有三篇博客:
这一篇我们来了解JDK8已经定义好的几个函数式接口
| 一、概述 |
jdk8之后新增的一个重要的包,java,util.function
该包下所有的接口都是函数式接口,按分类主要分为四大接口类型:Function、Consumer、Predicate、Supplier ,有关Predicate这里不再讲解


java.util.Function包如下


| 二、Consumer |
作用,一听这个名字就知道是消费某个对象,没有返回值
1、源码
@FunctionalInterface
public interface Consumer<T> { /**
* 抽象方法:传入一个指定泛型的参数,无返回值
*/
void accept(T t); /**
* 如同方法名字一样andThen,类似一种相加的功能(下面会举例说明)
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
2、使用示例
public static void main(String[] args) {
testConsumer();
testAndThen();
}
/**
* 一个简单的平方计算
*/
private static void testConsumer() {
//设置好consumer实现方法
Consumer<Integer> square=x-> System.out.println("平方计算:"+x*x);
square.accept(2);
}
/**
* 定义3个consumer并按顺序进行调研andThen方法
*/
private static void testAndThen() {
//当前值
Consumer<Integer> consumer1=x-> System.out.println("当前值:"+x);
//相加
Consumer<Integer> consumer2=x-> System.out.println("相加:"+(x+x));
//相乘
Consumer<Integer> consumer3=x-> System.out.println("相乘:"+x*x);
//andThen拼接
consumer1.andThen(consumer2).andThen(consumer3).accept(1);
}
运行结果:

单这样消费看去并没啥意义,但如果是集合操作就有意义了,所以jdk8的Iterator接口就引入了Consumer
3、JDK8使用
Iterable接口的forEach方法需要传入Consumer,大部分集合类都实现了该接口,用于返回Iterator对象进行迭代
public interface Iterable<T> {
//forEach方法传入的就是Consumer
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
我们在来看带来的便利
public static void main(String[] args) {
//1有个集合,集合里的对象有age
List<Student> studentList=new ArrayList<>();
for (Student student : studentList) {
student.setAge(1);
}
//2、通过forEach的Consumer添加
studentList.forEach(x->x.setAge(1));
}
这样一比较代码确实简洁了点,这就是Consumer给我们写代码带来简洁的地方
| 三、Supplier |
作用:提前定义可能返回的一个指定类型结果,等调用的时候在获取结果
1、源码
@FunctionalInterface
public interface Supplier<T> { /**
* 只有这一个抽象类
*/
T get();
}
源码非常简单
2、JDK8使用
在JDK8中Optional对象有使用到
Optional.orElseGet(Supplier<? extends T>)//当对象为null,就通过传入supplier创建一个返回
我们看下源码:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
使用示例
public static void main(String[] args) {
Person son = null;
//先判断son是否为null,如果为不为null则返回当前对象,如果为null则返回新创建的对象
BrandDTO optional = Optional.ofNullable(son).orElseGet(() -> new Person());
}
这样代码是不是又简单了。有关Optional下面会写一篇博客
| 四、Function |
作用,实现一个“一元函数”,即传入一个值经过函数的计算返回另外一个值
@FunctionalInterface
public interface Function<T, R> { /**
* 抽象方法: 根据一个数据类型T加工得到一个数据类型R
*/
R apply(T t); /**
* 组合函数,调用当前function之前调用
*/
default <V> java.util.function.Function<V, R> compose(java.util.function.Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
} /**
* 组合函数,调用当前function之后调用
*/
default <V> java.util.function.Function<T, V> andThen(java.util.function.Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
} /**
* 静态方法,返回与原函数参数一致的结果。x=y
*/
static <T> java.util.function.Function<T, T> identity() {
return t -> t;
}
}
使用示例
public static void main(String[] args) {
applyTest();
andThenTest();
composeTest();
test();
}
/**
* 1、apply示例
*/
private static void applyTest() {
//示例一:
Function<String,Integer> function=x->Integer.parseInt(x);
Integer a=function.apply("100");
System.out.println(a.getClass());
//结果:class java.lang.Integer
}
/**
* 2、andThen示例
*/
private static void andThenTest() {
//示例2:使用andThen()实现一个函数 y=10x+10;
//先执行 10*x
Function<Integer,Integer> function=x->10*x;
//通过andThen在执行,这里的x就等于上面的10*x的值
function=function.andThen(x->x+10);
System.out.println(function.apply(2));
//结果:30
}
/**
* 3、compose示例
*/
private static void composeTest() {
//示例3:使用compose()实现一个函数y=(10+x)2;
Function<Integer,Integer> function=x->x*2;
//先执行x+10在执行(x+10)*2顺序与上面相反
function=function.compose(x->x+10);
System.out.println(function.apply(3));
//结果:26
}
/**
* 4、总和示例
*/
private static void test() {
//示例4:使用compose()、andThen()实现一个函数 y=(10+x)*2+10;
//执行第二步
Function<Integer,Integer> function=x->x*2;
//执行第一步
function=function.compose(x->x+10);
//执行第三步
function=function.andThen(x->x+10);
System.out.println(function.apply(3));
//结果:36
}
3、JDK8使用
有两个地方很常用
1、V HashMap.computeIfAbsent(R,Function<K,V>) //简化代码,如果指定的键尚未与值关联或与null关联,使用函数返回值替换
2、<R>Stream<R> map(Function<?super T,? extends R> mapper);//转换流
computeIfAbsent使用示例
public static void main(String[] args) {
Map<String, List<String>> map = new HashMap<>();
List<String> list;
//java8之前的写法
list = map.get("key");
if (list==null){
list=new LinkedList<>();
map.put("key",list);
}
list.add("11");
//使用computeIfAbsent可以这样写,如果key返回不为空,则返回该集合,为空则创建集合返回
list=map.computeIfAbsent("key",k->new ArrayList<>());
list.add("11");
}
stream中map使用示例
public static void main(String[] args) {
List<Person> persionList = new ArrayList<Person>();
persionList.add(new Person("张三",28,"女"));
persionList.add(new Person("小小",2,"女"));
persionList.add(new Person("李四",65,"男"));
//只取出该集合中所有姓名组成一个新集合(将person对象转为string对象)
List<String> nameList=persionList.stream().map(Person::getName).collect(Collectors.toList());
System.out.println(nameList.toString());
//输出结果:[张三, 小小, 李四]
}
代码看上去又整洁了
总结:这些函数式接口作用在我看来,就是定义一个方法,方法中有个参数是函数式接口,这样的话函数的具体实现则由调用者来实现,这就是函数式接口的意义所在
一般我们也会很少去定义一个方法,方法参数包含函数接口,我们更重要的是学会使用JDK8中带有函数式接口参数的方法,来简化我们的代码
java代码(15) ---java8 Function 、Consumer 、Supplier的更多相关文章
- java代码之美(15)---Java8 Function、Consumer、Supplier
Java8 Function.Consumer.Supplier 有关JDK8新特性之前写了三篇博客: 1.java代码之美(1)---Java8 Lambda 2.java代码之美(2)---Jav ...
- java代码之美(16) ---Java8 Optional
Java8 Optional 一句话介绍Optional类:使用JDK8的Optional类来防止NullPointerException(空指针异常)问题. 一.前言 在我们开放过程中,碰到的异常中 ...
- Java8-四个函数式接口(Consumer,Supplier,Predicate,Function)
Java8---函数式接口 Consumer---消费者(accept方法,Lambda与方法引用返回都是Consumer) Supplier---供给型(get方法,返回数据,与Optional可以 ...
- java代码之美(14)---Java8 函数式接口
Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加 ...
- java代码(14) --Java8函数式接口
Java8函数式接口 之前有关JDK8的Lambda表达式 Java代码(1)--Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁 一.概 ...
- Jmeter4.0---- jmeter中写入java代码_简单了解(15)
1.说明 BeanShell:是一个小型嵌入式Java源代码解释器,具有对象脚本语言特性,能够动态地执行标准JAVA语法,并利用在JavaScript和Perl中常见的的松散类型.命令.闭包等通用脚本 ...
- [大牛翻译系列]Hadoop(15)MapReduce 性能调优:优化MapReduce的用户JAVA代码
6.4.5 优化MapReduce用户JAVA代码 MapReduce执行代码的方式和普通JAVA应用不同.这是由于MapReduce框架为了能够高效地处理海量数据,需要成百万次调用map和reduc ...
- Java学习之==>Java8 新特性详解
一.简介 Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.Java 8是 Java 自 Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库. ...
- 【Java基础】Java8 新特性
Java8 新特性 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).使用它可以写出更简洁.更灵活的代码. L ...
随机推荐
- 2020年腾讯实习生C++面试题&持续更新中(3)
2020年腾讯实习生C++面试题&持续更新中(3) hello,大家好,我是好好学习,天天编程的天天. 来给大家大家分享腾讯实习生面经了. 天天希望大家看到面经后一定要做充分的准备,结合自己掌 ...
- 【Django组件】KindEditor富文本编辑器上传文件,html样式文本,VUE异步提交数据(易懂版)
1:下载与配置 适合版本: python3 下载:http://kindeditor.net/down.php 文档:http://kindeditor.net/doc.php 将文件包放入stati ...
- Docker搭建代码检测平台SonarQube并检测maven项目
1 前言 良好的代码习惯是一个优秀程序员应该具备的品质,但靠人的习惯与记忆来保证代码质量,始终不是一件靠谱的事.在计算机行业应该深知,只要是人为的,都会有操作风险.本文讲解如何通过Docker搭建代码 ...
- 快速配置Samba服务
1.安装samba 这里以CenOS 7为例,其他系统类似 yum install samba samba-client samba-common 2.修改smb.conf 最好先备份原文件,以防 ...
- jdk1.8的一些特性
一.jdk1.8的特性: Lambda表达式 函数式接口 方法引用 接口的默认方法和静态方法 Optional Streams 并行数组 新时间日期API 二.Lambda表达式: Lambda 表达 ...
- 容器技术之Docker基础入门
前文我们了解了下LXC的基础用法以及图形管理工具LXC WEB Panel的简单使用,有兴趣的朋友可以参考https://www.cnblogs.com/qiuhom-1874/p/12904188. ...
- 201771010120 苏浪浪 《面向对象程序设计(java)》第11周学习总结
实验十一 集合 1.实验目的与要求 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API: (2) 了解java集合框架体系组成: (3) 掌握ArrayList.Lin ...
- php操作redis常用方法
1,connect 描述:实例连接到一个Redis. 参数:host: string,port: int 返回值:BOOL 成功返回:TRUE;失败返回:FALSE 示例: <?php $red ...
- 关于Java两点需要更新的知识
HashMap的初始容量 背景 很多人可以把HashMap的原理描述的很溜.比如JDK1.7之前,底层数据结构是数组+链表.JDK1.8之后,出于效率上的考虑,在数组长度大于64,链表长度大于8的时候 ...
- Android_基础之分辨率
常见屏幕分辨率对应尺寸 标屏 分辨率 比例 宽屏 分辨率 比例 QCIF 176X144 11:9 CIF 352X288 11:9 QVGA 320X240 4:3 WQVG ...