开口

JDK8 被称为 Lambda。很多人会用,比如Stream流,但是简单好用,比如调用集合的Stream API,但是不会定义自己的函数接口或者API。今天,我们通过几个案例来改进Java中函数编程的使用。

案例演示

功能接口说明

界面

输入参数

返回类型

解释

一元运算符

具有相同输入和输出类型的一元函数

谓词

布尔值

断言

消费者

/

消费一个数据,只有输入,没有输出

函数<T,R>

R

输入 T 返回 R,带有输入和输出

供应商

/

提供一个数据,没有输入,只有输出

双函数<T,U,R>

(T,U)

R

两个输入参数

双谓词<L, R>

(左,右)

布尔值

两个输入参数

BiConsumer<T, U>

(T,U)

空白

两个输入参数

二元运算符

(T,T)

具有相同输入和输出类型的二进制函数

案例一

函数<整数, 整数> times2 u003d e -> e * 2;

函数<整数, 整数> 平方 u003d e -> e * e;

// 先执行参数再执行调用者

/*

* 1. 4 * 4 u003d 16 16 * 2 u003d 32

*/

System.out.println("结果:" + times2.compose(squared).apply(4)); // 32

/*

* 先执行调用者:4 * 2 u003d 8,再执行当时传入的函数 8 * 8 u003d 64

*/

System.out.println("结果:" + times2.andThen(squared).apply(4)); // 64

和Then这两个方法是在Function外面执行之后调用的,compose表示Function在外面执行之前被调用。

案例二

@测试

公共无效 test2(){

// 添加三个数字

函数<整数, 函数<整数, IntFunction<整数>>> addfun3 u003d x -> y -> z -> x + y + z ;

// 添加 7 个数字

函数<整数,

函数<整数,

函数<整数,

函数<整数,

函数<整数,

函数<整数, IntFunction<整数>>>>>>>

addfun7 u003d x -> y -> z -> a -> c -> b -> d -> x + y + z + a + c + b + d;

// 1+2+3

整数和 u003d addfun3.apply(1).apply(2).apply(3);

System.out.println(sum);

}

这样就可以实现链式编程的累积效应

案例3

@SafeVarargs

私有静态 <R> 函数<R, R> combineFunctions(Function<R, R>...函数) {

返回 Arrays.stream(函数)

.reduce(函数::然后)

.orElseThrow(() -> new IllegalArgumentException("没有要组合的函数"));

}

@测试

公共无效 test3() {

函数<整数, 整数> addfun2 u003d x -> x * x;

最终整数应用 u003d combineFunctions(addfun2, addfun2).apply(2);

System.out.println(应用);

字符串 str u003d "1,2,3,4,5,6";

函数<Object, Object> splitByComma u003d s -> ((String) s).split(",");

Function<Object, Object> convertToInt u003d tokens -> Stream.of((String[]) tokens).map(Integer::valueOf).toArray(Integer[]::new);

Function<Object, Object> find Max u003d in -> Stream.of((Integer[]) int).max(Integer::compare).get();

Integer max u003d (Integer) combineFunctions(splitByComma, convertToInt, findMax).apply(str);

System.out.println(max);

}

如果想要有一个方法接受变长函数参数,可以使用Descriptor,其中泛型<R,R>代表输入和输入类型。泛型用于更高的兼容性

案例4

@测试

公共无效 test4(){

函数<整数, 整数> addfun2 u003d x -> x * x;

final Calculator<Integer, Integer> 计算器 u003d new Calculator<>(2);

最终整数整数 u003d 计算器.combineFunctions(addfun2, addfun2);

System.out.println(整数);

}

公共类计算器<R,T> {

// 要操作的属性

私有对象输入;

公共计算器(对象输入){

this.input u003d 输入;

}

// 可以这样定义对象本身的行为

@SuppressWarnings("未选中")

@SafeVarargs

公共最终 R combineFunctions(Function<T, T>... 函数) {

返回 (R) Arrays.stream(函数)

.reduce(函数::然后)

.orElseThrow(() -> new IllegalArgumentException("没有要组合的函数"))

.apply((T)输入);

}

}

领域开发模式已经或多或少地被听到和理解。除了自己的属性之外,对象还可以有自己的行为。对象的行为方法也可以由函数式编程范式定义。

案例5

// Biconsumer < T, Integer > 两个输入参数 T, Integer

公共静态 <T> Consumer<T> consumerWithIndex(BiConsumer<T, Integer> consumer) {

类对象 {

诠释我;

}

// 它只会被调用一次。原因取决于Java lang.Iterable#forEach

对象 obj u003d 新对象();

// 消费者函数返回

返回 t -> {

int 索引 u003d obj.i++;

// 执行系统。 Println("list [" + index + "] u003d" + item ") 消费指定泛型类型的数据。

消费者.accept(t, index);

};

}

@测试

公共无效 test5(){

val list u003d Arrays.asList("Hi", "I", "am", "Henry.Yao");

// 2 个元素为一组

val 分区 u003d Lists.partition(list, 2);

partition.forEach(LambdaUtils.consumerWithIndex((项目,索引)-> {

System.out.println("list[" + index + "]u003d" + item);

}));

}

Java 8 的 forEach() 循环对象时,无法获取对象索引下标。在这种情况下,您可以声明一个函数方法来执行此操作。最终的写法类似于Scala和js的forEach语法,非常好用!

java.lang.Iterable#forEach

// action: 是一个消费者函数

default void forEach(Consumer<? super T> action) {

Objects.requireNonNull(动作);

for (T t : 这个) {

/* 这里会循环调用Consumer函数,consumerWithIndex返回的Consumer函数内容为

t -> {

int 索引 u003d obj.i++;

消费者.accept(t, index);

}

因此,Obj obj u003d new Obj() 只会被调用一次,所以你不必担心如果在 new Obj 期间 i 没有被重置为 0,它就不会发生

*/

消费者.accept(t, index);

}

action.accept(t);

}

}

如果觉得文章对你有帮助,请点赞、评论、收藏。您的支持是我最大的动力!!!

最后小编在学习过程中整理了一些学习资料,可以分享给Java工程师朋友们互相交流学习,如有需要可以加入我的学习交流群323432957免费获取Java架构学习资料(包括高可用、高并发、高性能与分布式、Jvm性能调优、Spring源码、MyBatis、Netty、Redis、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点的架构资料。 )

作者:dingyu002

来源:dinyu002

版权归作者所有。如需商业转载,请联系作者授权。非商业转载请注明出处。

点击阅读全文
Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐