Java函数式编程随想

简介: Java函数式编程随想

java函数式编程的类主要定义在java.util.function包下。快速浏览了下该包下的一些类和接口。读者要想看懂function相关的源码,也需要对lambda表达式和泛型有一定的了解。本文只讲function包下的一些源码解析


Predicate接口


Predicate在java函数式编程中起到了过滤的作用。java 8函数编程引入了Stream类。该类配合function包下定义的一些接口,实现了一系列的函数式编程方法。 比如Stream类的过滤功能

过滤一些符合条件的数据
Stream<T> filter(Predicate<? super T> predicate);
//函数式编程的注解
@FunctionalInterface
public interface Predicate<T> {
    //判断t是否符合条件
    //例如判断一个数是否奇数 return t % 2 != 0
    boolean test(T t);
    //这个是接口的一个默认实现的方法表示两个Predicate之间是与的关系
    //例如Predicate<Integer> isOdd 表示筛选出奇数
    //Predicate<Integer> biggerThan10 表示筛选出大于10的数
    //Predicate<Integer> and = isOdd.and(biggerThan10)表示大于10的奇数
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
        //上面lambda等价于
        //final Predicate self = this;
        //return new Predicate<T>(){
        //     boolean test(T t){
        //        retun self.test(t) && other.test(t)
        //     }
        //}
    }
    //求反Predicate<T> isEven = isOdd.negate()表示筛选出偶数
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    //或的关系,用and的例子来讲 isOdd.or(biggerThan10)表示大于10或者是奇数的数
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
}


下面我们结合一个例子来了解下Predicate的原始用法(结合Stream使用才叫高级用法)


给定一个集合{1,2,3,4,5,6,7,8,9,10}我们要找出其中的奇数。结合Predicate我们可以这样实现

        Predicate<Integer> p = new Predicate<Integer>(){
            public boolean test(Integer o){
                return o % 2 != 0;
            }
        };
        Integer[] arr = {1,2,3,4,5,6,7,8,9,10};
        for(Integer i:arr){
            if(p.test(i)){
                System.out.print(i);//输出13579
            }
        }
        用lambda
        Predicate<Integer> p = o->  o % 2 != 0;
        Integer[] arr = {1,2,3,4,5,6,7,8,9,10};
        for(Integer i:arr){
            if(p.test(i)){
                System.out.println(i);
            }
        }
        用Stream
        IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            .filter(i -> i % 2 != 0)
            .forEach(i -> System.out.print(i));//输出13579

Consumer接口


public interface Consumer<T> {
    //根据传入的参数做出操作
    void accept(T t);
    //做完一个操作 接着做另一个操作
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

andThen等价于

    default Consumer<T> andThen(final Consumer<? super T> after) {
        Objects.requireNonNull(after);
        final Consumer<T> self = this;
        return new Consumer<T>() {
            @Override
            public void accept(T t) {
                self.accept(t) && after.accept(t);
            }
        }
    }

举个例子

    Consumer<Integer> c1 = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        };
        Consumer<Integer> c2 = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer*integer);
            }
        };
        c1.andThen(c2).accept(2);// 结果 2  4

主要用在Stream的forEach中

    void forEach(Consumer<? super T> action);

Function接口



Fuction

@FunctionalInterface
public interface Function<T, R> {
    //从T类型转换到R类型
    R apply(T t);
    //组合最终返回的是V->R的转换。首先是V->T 然后T->R的转换
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    //先转换T->R然后转换R->V最终返回的是T->V
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    /**
     * 返回自己
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

举例说明 将数字转换成相应的英文单词


 Map<Integer, String> map = new HashMap<>();
        map.put(1, "one");
        map.put(2, "two");
        map.put(3, "three");
        map.put(4, "four");
        map.put(5, "five");
        Function<Integer, String> function = new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) {
                return map.get(integer);
            }
        };
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept(function.apply(1));//结果 one

如果要获取数字对应的英文单词的字母个数呢


        Function<Integer, String> getLetter = new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) {
                return map.get(integer);
            }
        };
        Function<String, Integer> getLetterLength = new Function<String, Integer>() {
            @Override
            public Integer apply(String letter) {
                return letter.length();
            }
        };
        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer s) {
                System.out.println(s);
            }
        };
        consumer.accept(getLetter.andThen(getLetterLength).apply(1));//结果3

lambda表达式

 Consumer<Integer> consumer = System.out::print;
        Function<Integer, String> getLetter = i->map.get(i);
        Function<String, Integer> getLetterLength = s->s.length();
        Function<Integer, Integer> indexAndSize = getLetter.andThen(getLetterLength);
        consumer.accept(indexAndSize.apply(1));

Stream中使用


<R> Stream<R> map(Function<? super T, ? extends R> mapper);

用Stream实现一个简单的例子


打印从0到10 偶数对应的英文单词


        Map<Integer, String> map = new HashMap<>();
        map.put(0, "zero");
        map.put(1, "one");
        map.put(2, "two");
        map.put(3, "three");
        map.put(4, "four");
        map.put(5, "five");
        map.put(6, "six");
        map.put(7, "seven");
        map.put(8, "eight");
        map.put(9, "nine");
        Stream<Integer> stream = Stream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        stream.filter(i -> i % 2 == 0)
                .map(i -> map.get(i))
                .forEach(s -> System.out.println(s));
结果                
zero
two
four
six
eight


相关文章
|
2月前
|
Java 程序员 API
解锁Java新纪元:Lambda表达式——让你的代码秒变高大上,函数式编程不再是梦!
【8月更文挑战第25天】Java 8 推出了革命性的 Lambda 表达式特性,这是一种匿名函数形式,支持任意数量参数及返回值,简化了代码编写。其基本语法为 `(parameters) -&gt; expression` 或 `(parameters) -&gt; { statements; }`。例如,遍历集合可从使用匿名内部类变为简洁的 `names.forEach(name -&gt; System.out.println(name))`。
42 0
|
7天前
|
并行计算 Java 测试技术
探索Java中的函数式编程
在本文中,我们将深入探讨Java中的函数式编程。我们会先了解什么是函数式编程以及为什么它如此重要。然后,通过一些简单的代码示例,展示如何在Java中应用函数式编程概念。最后,讨论在实际项目中如何利用函数式编程来提高代码的可读性和效率。
|
9天前
|
Java API 开发者
探索Java中的函数式编程
本文深入探讨了Java中的函数式编程,这是一种强调使用不可变数据和避免共享状态的编程范式。我们将从基础概念、核心特性以及实际应用案例三个方面,全面解析函数式编程在Java中的魅力和价值。
|
8天前
|
Java C语言
5-13|Java的函数式编程
5-13|Java的函数式编程
|
3月前
|
并行计算 Java API
深入理解Java中的Lambda表达式与函数式接口
【7月更文挑战第19天】在Java 8中引入的Lambda表达式,不仅简化了代码编写,还为函数式编程提供了支持。本文将探讨Lambda表达式的核心概念、其与函数式接口的关系以及如何在Java中高效利用这一特性来提升代码的简洁性和可读性。我们将通过实例分析Lambda表达式的语法规则和常见用法,同时解释函数式接口的设计原则及其在Java标准库中的应用,旨在帮助开发者更好地理解和运用这一强大的工具。
|
1月前
|
Java
盘点java8 stream中隐藏的函数式接口
`shigen`是一位坚持更新文章的博客作者,记录成长历程,分享认知见解,留住感动瞬间。本文介绍了函数式接口的概念及其在Java中的应用,包括`Comparator`、`Runnable`、`Callable`等常见接口,并详细讲解了`Function`、`Predicate`、`Consumer`、`Supplier`和`Comparator`等函数式接口的使用方法及应用场景,展示了如何利用这些接口简化代码并提高编程效率。**个人IP:shigen**,与shigen一起,每天进步一点点!
33 0
盘点java8 stream中隐藏的函数式接口
|
2月前
|
Java 编译器 开发者
Java中的Lambda表达式与函数式接口
【8月更文挑战第31天】本文将深入探讨Java 8中引入的Lambda表达式和函数式接口,它们如何改变我们编写代码的方式。通过简化集合操作、事件处理等示例,我们将看到这些特性如何提升代码可读性、减少冗余,并提高开发效率。准备好一起探索这个让Java编程更加简洁强大的新世界吧!
|
2月前
|
并行计算 Java 大数据
Java函数式编程:一场编程范式的革命,让你的代码焕发新生!
【8月更文挑战第30天】Java函数式编程是一种基于数学函数理论的编程范式,强调数据处理的不可变性和纯函数使用,通过将函数视为第一类对象,实现更简洁、易读的代码结构,在数据流处理与并行计算中尤为突出。与命令式编程关注执行步骤不同,函数式编程侧重描述计算目标而非具体操作流程,减少了状态变化,使代码更清晰易维护。在Java中,函数式编程通过降低副作用和状态依赖简化了复杂度,并提高了代码质量和测试性,尤其是在Java 8的Stream API中得到了充分体现,能够自动优化多核处理器上的并行处理性能。
38 2
|
2月前
|
Java 开发者
Java 8新特性之Lambda表达式与函数式接口
【7月更文挑战第59天】本文将介绍Java 8中的一个重要新特性——Lambda表达式,以及与之密切相关的函数式接口。通过对比传统的匿名内部类,我们将探讨Lambda表达式的语法、使用方法和优势。同时,我们还将了解函数式接口的定义和用途,以及如何将Lambda表达式应用于函数式编程。
|
2月前
|
分布式计算 Java API
Java 8带来了流处理与函数式编程等新特性,极大提升了开发效率
Java 8带来了流处理与函数式编程等新特性,极大提升了开发效率。流处理采用声明式编程模型,通过filter、map等操作简化数据集处理,提高代码可读性。Lambda表达式支持轻量级函数定义,配合Predicate、Function等接口,使函数式编程无缝融入Java。此外,Optional类及新日期时间API等增强功能,让开发者能更优雅地处理潜在错误,编写出更健壮的应用程序。
26 1
下一篇
无影云桌面