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

相关文章
|
23天前
|
Java
Java8函数式编程
Java8函数式编程
24 2
|
3月前
|
Java 程序员 API
解锁Java新纪元:Lambda表达式——让你的代码秒变高大上,函数式编程不再是梦!
【8月更文挑战第25天】Java 8 推出了革命性的 Lambda 表达式特性,这是一种匿名函数形式,支持任意数量参数及返回值,简化了代码编写。其基本语法为 `(parameters) -&gt; expression` 或 `(parameters) -&gt; { statements; }`。例如,遍历集合可从使用匿名内部类变为简洁的 `names.forEach(name -&gt; System.out.println(name))`。
53 0
|
6天前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
7天前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
17 4
|
11天前
|
Java API 开发者
Java中的Lambda表达式与函数式编程####
在Java的演变过程中,Lambda表达式和函数式编程的引入无疑是一次重大的飞跃。本文将深入探讨Lambda表达式的定义、用法及优势,并结合实例说明如何在Java中利用Lambda表达式进行函数式编程。通过对比传统编程方式,揭示Lambda表达式如何简化代码、提高开发效率和可维护性。 ####
|
1月前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
24 1
|
2月前
|
并行计算 Java 测试技术
探索Java中的函数式编程
在本文中,我们将深入探讨Java中的函数式编程。我们会先了解什么是函数式编程以及为什么它如此重要。然后,通过一些简单的代码示例,展示如何在Java中应用函数式编程概念。最后,讨论在实际项目中如何利用函数式编程来提高代码的可读性和效率。
29 7
|
2月前
|
Java API 开发者
探索Java中的函数式编程
本文深入探讨了Java中的函数式编程,这是一种强调使用不可变数据和避免共享状态的编程范式。我们将从基础概念、核心特性以及实际应用案例三个方面,全面解析函数式编程在Java中的魅力和价值。
|
2月前
|
Java C语言
5-13|Java的函数式编程
5-13|Java的函数式编程
|
3月前
|
并行计算 Java 大数据
Java函数式编程:一场编程范式的革命,让你的代码焕发新生!
【8月更文挑战第30天】Java函数式编程是一种基于数学函数理论的编程范式,强调数据处理的不可变性和纯函数使用,通过将函数视为第一类对象,实现更简洁、易读的代码结构,在数据流处理与并行计算中尤为突出。与命令式编程关注执行步骤不同,函数式编程侧重描述计算目标而非具体操作流程,减少了状态变化,使代码更清晰易维护。在Java中,函数式编程通过降低副作用和状态依赖简化了复杂度,并提高了代码质量和测试性,尤其是在Java 8的Stream API中得到了充分体现,能够自动优化多核处理器上的并行处理性能。
56 2