JAVA基础 函数式编程 2

简介: JAVA基础 函数式编程

ed4b459c6698493e9422ee8f030b1bb4.png 1.3.5 Lambda 表达式中的闭包问题

什么是闭包

闭包的本质就是代码片断。所以闭包可以理解成一个代码片断的引用。在Java中匿名内部类也是闭包的一种实现方式。

在闭包中访问外部的变量时,外部变量必须是final类型,虚拟机会帮我们加上 final 修饰关键字。

二、常用函数接口

2.1 Consumer接口的使用

Consumer 接口是JDK为我们提供的一个函数式接口,该接口也被称为消费型接口。


遍历集合


我们可以调用集合的 public void forEach(Consumer<? super E> action) 方法,通过 lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操作。


实现方式一:

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
class ConsumerImpl implements Consumer {
    //Object就是要消费的数据。
    @Override
    public void accept(Object o) {
        System.out.println(o+"O(∩_∩)O");
    }
}
public class TestConsumer {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
       /* forEach可以实现取出集合中的元素但是不知道怎么处理取出的元素。
        forEach方法需要的参数是Consumer接口实现类的对象,也就是说我需要给forEach
        一个能消费它遍历出来的元素的对象。*/
        list.forEach(new ConsumerImpl());
    }
}

方式二:

如果仅仅是为了输出遍历的数据的话,这样写未免有些麻烦。我们平时使用的输出语句是System.out.println,打开API文档

我们可以发现,out实际上是System类下的静态成员变量,返回的是一个PrintStream类型的数据,该类下的println方法是个无返回值的含有一个Object类型参数的非静态方法。这和Consumer接口中的抽象方法accept的结构一毛一样,因此我们可以使用Lambda表达式将printlin方法作为accept的实现方法。

package cn.it.bz.Lambda;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
public class TestConsumer {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        //将PrintStream类下的println方法作为Consumer接口的抽象方法accept方法的实现方法。
        PrintStream out = System.out;
        list.forEach(out::println);
    }
}

8692f40ee17b4376afe5cb4efc1c6d3b.png

2.2 Predicate接口的使用

Predicate 是 JDK 为我们提供的一个函数式接口,可以简化程序的编写。

删除集合中的元素

我们通过public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元素,

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
class PredicateImpl implements Predicate {
    @Override
    public boolean test(Object o) {
        return "b".equals(o);
    }
}
public class TestPredicate {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        //实例化PredicateImpl
        PredicateImpl predicateImpl = new PredicateImpl();
        list.removeIf(predicateImpl);
//        //或者使用Lambda表达式
//        list.removeIf((o)-> o.equals("b"));
        //查看集合中是否还存在b元素
        Consumer consumer = (a) -> System.out.println(a);
        list.forEach(consumer);
    }
}

2.3 Comparator接口的使用

Comparator是 JDK 为我们提供的一个函数式接口,该接口为比较器接口。

元素排序

之前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器重写 compare 方法的比较器对象,现在我们还可以使用 lambda 表达式来简化代码。

排序方式一:

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
class ComparatorImpl implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
}
public class TestComparator {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("c");
        list.add("d");
        list.add("b");
        list.add("a");
        //元素排序
        ComparatorImpl comparatorImpl = new ComparatorImpl();
        list.sort(comparatorImpl);
        //输出
        list.forEach(System.out::println);
    }
}

方式二使用Lambda表达式、

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.List;
public class TestComparator {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("c");
        list.add("d");
        list.add("b");
        list.add("a");
        //元素排序
        list.sort((o1,o2) ->o1.compareTo(o2));
        //输出
        list.forEach(System.out::println);
    }
}

三、Stream流

3.1 Stream流简介

Stream是数据渠道,用于操作数据源所生成的元素序列,它可以实现对集合的复杂操作,例如过滤、排序和映射等。Stream不会改变源对象,而是返回一个新的结果集。

Stream流的生成方式

  • 生成流:通过数据源(集合、数组等)创建一个流。
  • 中间操作:一个流后面可以跟随零个或者多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用。

终结操作:一旦执行终止操作,就执行中间的链式操作,并产生结果。

collection接口中有一个Stream类型的方法,该接口下的实现类实现了该抽象方法,也就是说Collection接口下的List、set等单例集合都存在一个Stream方法返回一个对应的Streatm对象。


3.2 Stream流的常见方法

3.2.1 数据过滤

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStream {
    public static void main(String[] args) {
        //生成Stream流对象
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("O(∩_∩)O");
        list.add("张三");
        list.add("张无形");
        Stream<String> stream = list.stream();
        //操作流对象
        //数据过滤,实现多条件and关系,以张开头三结尾的元素
        List<String> collect = stream.filter(o -> o.startsWith("张")).filter(o -> o.endsWith("三")).collect(Collectors.toList());
        //遍历过滤后的结合
        collect.forEach(System.out::println);
        System.out.println("--------------------");
        Stream<String> stream1 = list.stream();
        //多条件的or关系
        //先创建or关系
        Predicate<String> predicate = (o) ->o.startsWith("张");
        Predicate<String> predicate2 = (o) -> o.startsWith("O");
        List<String> collect1 = stream1.filter(predicate.or(predicate2)).collect(Collectors.toList());
        //遍历过滤后的结合
        collect1.forEach(System.out::println);
    }
}

3.2.2 数量限制

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStream2 {
    public static void main(String[] args) {
        //生成Stream流对象
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("O(∩_∩)O");
        list.add("张三");
        list.add("张无形");
        Stream<String> stream = list.stream();
        //获取前两个元素
        List<String> collect = stream.limit(2).collect(Collectors.toList());
        //遍历
        collect.forEach(System.out:: println);
    }
}

3.2.3 元素排序

package cn.it.bz.Lambda;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStream3 {
    public static void main(String[] args) {
        //生成Stream流对象
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("O(∩_∩)O");
        list.add("张三");
        list.add("张无形");
        //按照升序排序
        List<String> collect = list.stream().sorted().collect(Collectors.toList());
        //遍历
        collect.forEach(System.out::println);
        System.out.println("--------------------");
        //降序
        list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
    }
}


ed4b459c6698493e9422ee8f030b1bb4.png

相关文章
|
4天前
|
Java API 容器
Java 8中的函数式编程特性
【5月更文挑战第28天】 本文将深入探讨Java 8中引入的函数式编程特性,包括Lambda表达式、Stream API和Optional类。我们将通过实例和代码示例来展示这些特性如何简化代码、提高可读性和性能。我们还将讨论一些常见的使用场景和最佳实践,以帮助您更好地利用Java 8的函数式编程特性。
|
3天前
|
Java 程序员 API
Java 8新特性之函数式编程实践
【5月更文挑战第29天】本文将深入探讨Java 8引入的函数式编程特性,重点解析Lambda表达式、Stream API以及Optional类的应用。我们将通过实例演示如何利用这些工具简化代码,提高程序的可读性和效率。文章不仅涉及理论知识,更注重实战技巧,旨在帮助开发者掌握并有效应用Java 8的函数式编程特性。
8 0
|
15天前
|
移动开发 搜索推荐 Java
Java如何支持函数式编程?,作为移动开发程序员应该怎样去规划自己的学习路线
Java如何支持函数式编程?,作为移动开发程序员应该怎样去规划自己的学习路线
|
17天前
|
Java API 容器
Java8函数式编程接口:Consumer、Supplier、Function、Predicate
Java8函数式编程接口:Consumer、Supplier、Function、Predicate
10 1
|
17天前
|
Java 数据处理 API
Java 函数式编程:概念、优势与实战示例
【4月更文挑战第27天】函数式编程(Functional Programming,简称 FP)是一种编程范式,它将计算视为数学函数的求值并避免使用程序状态以及可变数据。
32 1
|
17天前
|
并行计算 Java API
【专栏】Java 8的Lambda表达式增强了函数式编程,允许以匿名函数形式传递行为
【4月更文挑战第27天】Java 8的Lambda表达式增强了函数式编程,允许以匿名函数形式传递行为。其基本语法`(params) -> expression/statements`,类型由参数推断,可引用final或effectively final的外部变量。Lambda广泛应用于集合操作(如Stream API)、并行流处理和GUI事件处理,简化代码并提高效率。通过实例,展示了Lambda在集合筛选、并行计算和事件处理中的应用,从而提高开发质量和效率。
|
17天前
|
安全 Java API
函数式编程在Java中的应用
【4月更文挑战第18天】本文介绍了函数式编程的核心概念,包括不可变性、纯函数、高阶函数和函数组合,并展示了Java 8如何通过Lambda表达式、Stream API、Optional类和函数式接口支持函数式编程。通过实际应用案例,阐述了函数式编程在集合处理、并发编程和错误处理中的应用。结论指出,函数式编程能提升Java代码的质量和可维护性,随着Java语言的演进,函数式特性将更加丰富。
|
17天前
|
Java API 开发者
Java 8新特性之函数式编程实战
【4月更文挑战第9天】本文将深入探讨Java 8的新特性之一——函数式编程,通过实例演示如何运用Lambda表达式、Stream API等技术,提高代码的简洁性和执行效率。
|
17天前
|
分布式计算 Java API
Java 8新特性详解:流处理与函数式编程
【4月更文挑战第2天】Java 8引入了流处理和函数式编程,革新了数据处理。流提供声明式处理,简化集合操作,利用filter、map等方法实现高效逻辑。Lambda表达式支持匿名函数,简化接口实现,配合函数式接口如Predicate和Function,增强代码简洁性。Optional类处理可能为空的值,防止空指针异常。新日期时间API和并行流进一步强化了函数式编程。这些特性提升了Java的效率和可读性,助力开发更优质的应用。
|
17天前
|
Java API
Java中的Lambda表达式和函数式编程
传统的Java编程方式在处理一些简单的逻辑时显得繁琐,而Lambda表达式的引入为我们提供了一种更加简洁、灵活的编程方式。本文将介绍Lambda表达式和函数式编程在Java中的应用以及其与传统编程方式的对比,帮助读者更好地理解并运用这一特性。
11 0