java 函数式编程应用_Java函数式编程原理以及应用

一. 函数式编程

Java8所有的新特性基本基于函数式编程的思想,函数式编程的带来,给Java注入了新鲜的活力。

下面来近距离观察一下函数式编程的几个特点:

函数可以作为变量、参数、返回值和数据类型。

基于表达式来替代方法的调用

函数无状态,可以并发和独立使用

函数无副作用,不会修改外部的变量

函数结果确定性;同样的输入,必然会有同样的结果。

下面jdk1.8里面对函数式编程的定义。只是一个  FunctionalInterface接口。特别的简单。

1 @Documented2 @Retention(RetentionPolicy.RUNTIME)3 @Target(ElementType.TYPE)4 public @interface FunctionalInterface {}

这个函数式接口有几点以下的限制:

唯一的抽象方法,有且仅有一个 (即所有的函数式接口,有且只能有一个抽象方法)

加上标注,则会触发JavaCompiler的检查。对于符合函数接口的接口,加不加都无关紧要,但是加上则会提供一层编译检查的保障。如果不符合,则会报错。

不能被覆盖之后,再声明为抽象方法,则不算抽象方法。例如接口实现了Object中的方法。

可用于lambda类型的使用方式

二. Java8新增函数式接口

Stream的操作是建立在函数式接口的组合之上的。Java8中新增的函数式接口都在java.util.function包下。这些函数式接口可以有多种分类方式。

2.1 Function

Function是从T到R的一元映射函数。将参数T传递给一个函数,返回R。即R = Function(T)

Function最常用的应该是   Stream map(Function super T, ? extends R> mapper);

比如List person里面有age,name…. 我传入age,他就会返回age的集合给我。

1 @FunctionalInterface2 public interface Function{3

4 R apply(T t);5

6 default Function compose(Function super V, ? extends T>before) {7 Objects.requireNonNull(before);8 return (V v) ->apply(before.apply(v));9 }10

11 default Function andThen(Function super R, ? extends V>after) {12 Objects.requireNonNull(after);13 return (T t) ->after.apply(apply(t));14 }15

16 static Functionidentity() {17 return t ->t;18 }19 }

2.2 Predicate

Predicate是一个谓词函数,主要作为一个谓词演算推导真假值存在,返回布尔值的函数。Predicate等价于一个Function的boolean型返回值的子集。

predicate最常用的莫过于  Stream filter(Predicate super T> predicate);

比如我要过滤年龄 > 18 的人,我传入age,判断是否为true。为true则保留,false丢弃。

1 @FunctionalInterface2 public interface Predicate{3

4 booleantest(T t);5

6 default Predicate and(Predicate super T>other) {7 Objects.requireNonNull(other);8 return (t) -> test(t) &&other.test(t);9 }10

11 default Predicatenegate() {12 return (t) -> !test(t);13 }14

15 default Predicate or(Predicate super T>other) {16 Objects.requireNonNull(other);17 return (t) -> test(t) ||other.test(t);18 }19

20 static PredicateisEqual(Object targetRef) {21 return (null ==targetRef)22 ?Objects::isNull23 : object ->targetRef.equals(object);24 }25 }

2.3 Consumer

Consumer是从T到void的一元函数,接受一个入参但不返回任何结果的操作。

Consumer最常用的肯定是   default void forEach(Consumer super T> action) {}

这是一段forEach循环的代码,传入实现的方法,并不返回任何值。只是循环。

1 @FunctionalInterface2 public interface Consumer{3

4 voidaccept(T t);5

6 default Consumer andThen(Consumer super T>after) {7 Objects.requireNonNull(after);8 return (T t) ->{ accept(t); after.accept(t); };9 }10 }

三. Lambda表达式

3.1 基本语法

Lambda 的基本结构为 (arguments) -> body,有如下几种情况:

参数类型可推导时,不需要指定类型,如 (a) -> System.out.println(a)

当只有一个参数且类型可推导时,不强制写 (), 如 a -> System.out.println(a)

参数指定类型时,必须有括号,如 (int a) -> System.out.println(a)

参数可以为空,如 () -> System.out.println(“hello”)

body 需要用 {} 包含语句,当只有一条语句时 {} 可省略

3.2 Lambda原理

比如如下代码:

1 List list = new ArrayList<>();2

3 list.stream().filter((x) -> x >= 18)4

5 Stream filter(Predicate super T>predicate);6

7 @FunctionalInterface8 public interface Predicate{9

10 booleantest(T t);11

12 }

比如List里面存个个人的年龄,现在筛选出年龄大于等于18的人。

此时我们就可以用  list.stream().filter((x) -> x >= 18)这就是一个典型的lambda表达式

(x) -> x >= 18传给  Predicate函数式接口。

原理其实是:

JVM帮我们动态生成了一个内部类,然后这个内部类实现了 Predicate这个函数式接口。

重写了里面的test方法。生成的类似如下:

1 static final class Main$$Lambda$1 implements Predicate{2 private Main$$Lambda$1() {3 }4

5 @Override6 public booleantest(Integer x) {7 return x >= 18;8 }9 }

3.3 Lambda用法

1 public classMain {2 public static voidmain(String[] args) {3

4 List list = new ArrayList<>();5 list.add(40);6 list.add(50);7 list.add(20);8 list.add(30);9 List collect = list.stream().filter(x -> x >= 30)10 .map((x) -> x + 10).sorted((x, y) -> -x.compareTo(y))11 .collect(Collectors.toList());12 System.out.println(collect);13 }14 }

这个一段很典型的Lambda + Stream的用法。

list.stream()获取list的stream的流

filter筛选出年龄大于30的人 (里面是一个Predicate接口,返回真假)

map做一个function映射

sort排序,里面是compartor

四. 总结

Lambda 表达式可以减少很多代码,能提高生产力。但也要理解其原理。比如3.3中的代码,为什么filter里面是断言表达式,map里面是function表达式。

这都要从lambda的原理入手,也就是JVM动态生成一个内部类,并继承其中的抽象方法。

本次主要介绍了Java函数式编程的原理以及应用,主要从Stream和lambda入手。通过一些简单的概念,以及代码,更好的理解Java的函数式编程。

掌握Java的函数式编程,对平时我们开发代码,看其他人的代码,都有很大的帮助。

且行且珍惜,加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值