Java函数式编程原理以及应用
一. 函数式编程Java8所有的新特性基本基于函数式编程的思想,函数式编程的带来,给Java注入了新鲜的活力。 下面来近距离观察一下函数式编程的几个特点:
下面jdk1.8里面对函数式编程的定义。只是一个??FunctionalInterface?接口。特别的简单。 1 @Documented 2 @Retention(RetentionPolicy.RUNTIME) 3 @Target(ElementType.TYPE) 4 public @interface FunctionalInterface {} 这个函数式接口有几点以下的限制:
? 二. Java8新增函数式接口Stream的操作是建立在函数式接口的组合之上的。Java8中新增的函数式接口都在java.util.function包下。这些函数式接口可以有多种分类方式。 2.1 FunctionFunction是从T到R的一元映射函数。将参数T传递给一个函数,返回R。即R = Function(T) Function最常用的应该是??<R> Stream<R> map(Function<? super T,? extends R> mapper); 比如List<Person> person里面有age,name.... 我传入age,他就会返回age的集合给我。 1 @FunctionalInterface 2 public interface Function<T,R> { 3 4 R apply(T t); 5 6 default <V> Function<V,R> compose(Function<? super V,? extends T> before) { 7 Objects.requireNonNull(before); 8 return (V v) -> apply(before.apply(v)); 9 } 10 11 default <V> Function<T,V> andThen(Function<? super R,? extends V> after) { 12 Objects.requireNonNull(after); 13 return (T t) -> after.apply(apply(t)); 14 } 15 16 static <T> Function<T,T> identity() { 17 return t -> t; 18 } 19 } ? 2.2?PredicatePredicate是一个谓词函数,主要作为一个谓词演算推导真假值存在,返回布尔值的函数。Predicate等价于一个Function的boolean型返回值的子集。 predicate最常用的莫过于??Stream<T> filter(Predicate<? super T> predicate);?? 比如我要过滤年龄 > 18 的人,我传入age,判断是否为true。为true则保留,false丢弃。 1 @FunctionalInterface 2 public interface Predicate<T> { 3 4 boolean test(T t); 5 6 default Predicate<T> and(Predicate<? super T> other) { 7 Objects.requireNonNull(other); 8 return (t) -> test(t) && other.test(t); 9 } 10 11 default Predicate<T> negate() { 12 return (t) -> !test(t); 13 } 14 15 default Predicate<T> or(Predicate<? super T> other) { 16 Objects.requireNonNull(other); 17 return (t) -> test(t) || other.test(t); 18 } 19 20 static <T> Predicate<T> isEqual(Object targetRef) { 21 return (null == targetRef) 22 ? Objects::isNull 23 : object -> targetRef.equals(object); 24 } 25 } ? 2.3?ConsumerConsumer是从T到void的一元函数,接受一个入参但不返回任何结果的操作。 Consumer最常用的肯定是? ?default void forEach(Consumer<? super T> action) {} 这是一段forEach循环的代码,传入实现的方法,并不返回任何值。只是循环。 1 @FunctionalInterface 2 public interface Consumer<T> { 3 4 void accept(T t); 5 6 default Consumer<T> andThen(Consumer<? super T> after) { 7 Objects.requireNonNull(after); 8 return (T t) -> { accept(t); after.accept(t); }; 9 } 10 } ? 三. Lambda表达式3.1?基本语法Lambda 的基本结构为?
? 3.2 Lambda原理比如如下代码: 1 List<Integer> list = new ArrayList<>(); 2 3 list.stream().filter((x) -> x >= 18) 4 5 Stream<T> filter(Predicate<? super T> predicate); 6 7 @FunctionalInterface 8 public interface Predicate<T> { 9 10 boolean test(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<Integer> { 2 private Main$$Lambda$1() { 3 } 4 5 @Override 6 public boolean test(Integer x) { 7 return x >= 18; 8 } 9 } ? 3.3 Lambda用法1 public class Main { 2 public static void main(String[] args) { 3 4 List<Integer> list = new ArrayList<>(); 5 list.add(40); 6 list.add(50); 7 list.add(20); 8 list.add(30); 9 List<Integer> 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的用法。
? 四. 总结Lambda 表达式可以减少很多代码,能提高生产力。但也要理解其原理。比如3.3中的代码,为什么filter里面是断言表达式,map里面是function表达式。 这都要从lambda的原理入手,也就是JVM动态生成一个内部类,并继承其中的抽象方法。 本次主要介绍了Java函数式编程的原理以及应用,主要从Stream和lambda入手。通过一些简单的概念,以及代码,更好的理解Java的函数式编程。 掌握Java的函数式编程,对平时我们开发代码,看其他人的代码,都有很大的帮助。 且行且珍惜,加油! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 在Java中嵌入Office
- java – 在GWT中构建SuggestBox后添加/修改SuggestOracle
- haskell如何从此代码中删除列表用法?
- spring boot+mybatis 多数据源切换(实例讲解)
- java – 使用DataSource连接到带有(Xerial)sqlite-jdbc驱动
- java8在Collection中新增加的方法removeIf
- 为什么不能将java包命名为“default”?
- Servlet获取AJAX POST请求中参数以form data和request payl
- 在Java bean中声明枚举变量
- 如何使用枚举或任何其他方式在java中构建类别的层次结构树?