首页 > 编程语言 >带你理解 Java 8 的函数式接口使用和自定义

带你理解 Java 8 的函数式接口使用和自定义

时间:2023-11-06 11:37:13浏览次数:25  
标签:Java 函数 自定义 List 接口 Supplier 方法 public

函数式接口是 Java 8 引入的一种接口,用于支持函数式编程。函数式接口通常包含一个抽象方法,可以被 Lambda 表达式或方法引用所实现。在本文中,我们将深入探讨函数式接口的概念、用途以及如何创建和使用函数式接口。

什么是函数式接口

函数式接口是只包含一个抽象方法的接口。但是默认方法和静态方法在此接口中可以定义多个。Java 中的函数式接口可以被用作 Lambda 表达式的目标类型。通过函数式接口,可以实现更简洁、更具可读性的代码,从而支持函数式编程的思想。

常见函数式接口

Java 中有一些内置的函数式接口,用于不同的用途:

  1. Runnable 用于描述可以在单独线程中执行的任务。
  2. Callable 类似于 Runnable,但可以返回执行结果或抛出异常。
  3. Comparator 用于比较两个对象的顺序。
  4. Function 接受一个参数并产生一个结果。
  5. Predicate 接受一个参数并返回一个布尔值,用于判断条件是否满足。
  6. Supplier 不接受参数,但返回一个值。

自定义函数式接口

自定义函数式接口是需要在接口上添加 @FunctionalInterface 注解

定义 CustomFunctionalInterface 接口函数

@java.lang.FunctionalInterface
public interface CustomFunctionalInterface {
   void execute();
}

在上述代码中,定义了一个名为 CustomFunctionalInterface 的函数式接口,其中包含一个抽象方法 execute,这是一个无参无返回值的方法。通过使用 @FunctionalInterface 注解,明确告诉编译器这是一个函数式接口,确保它只包含一个抽象方法。

基于 CustomFunctionalInterface 使用

public class CustomFunctionInterfaceTest {

  public void test(CustomFunctionalInterface functionalInterface) {
    functionalInterface.execute();
  }

  @Test
  public void execute() {
    test(() -> System.out.println("Hello World Custom!"));
  }
}

在测试类 CustomFunctionInterfaceTest 中,定义了一个名为 test 的方法,接受一个 CustomFunctionalInterface 参数,并在方法体中调用了 execute 方法。这个方法允许将任意实现了 CustomFunctionalInterface 的 Lambda 表达式传递进来,并执行其 execute 方法。

在测试方法 execute 中,通过调用 test 方法,传递了一个 Lambda 表达式 () -> System.out.println("Hello World Custom!")。这个 Lambda 表达式实现了 CustomFunctionalInterface 的抽象方法 execute,即打印了一条 "Hello World Custom!" 的消息。

常见函数式接口基本使用

Predicate

当涉及到对集合或数据进行筛选时,Java 中的函数式接口 Predicate 可以发挥重要作用。Predicate 是一个通用的函数式接口,用于定义一个接受参数并返回布尔值的操作,用于判断条件是否满足。

Predicate 函数式接口

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

基于 Predicate 进行筛选

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class PredicateExample {

    public static List<String> filterStrings(List<String> list, Predicate<String> predicate) {
        List<String> filteredList = new ArrayList<>();
        for (String str : list) {
            if (predicate.test(str)) {
                filteredList.add(str);
            }
        }
        return filteredList;
    }

    public static void main(String[] args) {
        List<String> stringList = List.of("apple", "banana", "cherry", "date", "elderberry");
        Predicate<String> lengthPredicate = str -> str.length() > 5;
        List<String> longStrings = filterStrings(stringList, lengthPredicate);
        System.out.println("Long strings: " + longStrings);
    }
}

在这个示例中,我们定义了一个 filterStrings 方法,它接受一个字符串列表和一个 Predicate 参数,并返回符合条件的字符串列表。在 main 方法中,我们创建了一个长度判断的 Predicate,然后使用它来筛选出长度大于 5 的字符串。

Consumer

函数式接口 Consumer 在 Java 中用于表示接受一个参数并且没有返回值的操作。它可以用于执行一些对输入数据的处理,例如打印、修改等。

Consumer 函数式接口

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

基于 Consumer 进行筛选

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {

        public static void processIntegers(List<Integer> list, Consumer<Integer> consumer) {
        for (Integer num : list) {
            consumer.accept(num);
        }
    }

    public static void main(String[] args) {
        List<Integer> integerList = List.of(1, 2, 3, 4, 5);
        Consumer<Integer> squareAndPrint = num -> {
            int square = num * num;
            System.out.println("Square of " + num + " is: " + square);
        };
        processIntegers(integerList, squareAndPrint);
    }
}

在这个示例中,我们定义了一个 filterStrings 方法,它接受一个字符串列表和一个 Predicate 参数,并返回符合条件的字符串列表。在 main 方法中,我们创建了一个长度判断的 Predicate,然后使用它来筛选出长度大于 5 的字符串。

在这个示例中,我们定义了一个 processIntegers 方法,它接受一个整数列表和一个 Consumer 参数,并在方法内遍历列表,对每个元素执行 accept 方法。在 main 方法中,我们创建了一个 Consumer 实现 squareAndPrint,它会计算每个元素的平方并打印出来。

Function

函数式接口 Function 在 Java 中用于表示一个接受一个参数并产生一个结果的操作。它可以用于执行各种转换、映射和处理操作。

Function 函数式接口

Function 接口定义了一个名为 apply 的抽象方法,接受一个参数并返回一个结果。这个接口用于表示一个对输入数据的转换操作。

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

在上述定义中,T 表示输入类型,R 表示输出类型。

基于 Function 进行数据转换

转换为大写
import java.util.function.Function;

public class FunctionExample {

    public static String convertToUpperCase(String input, Function<String, String> function) {
        return function.apply(input);
    }
    public static void main(String[] args) {
        String original = "hello world";
        String upperCase = convertToUpperCase(original, str -> str.toUpperCase());
        System.out.println(upperCase);
    }
}

在这个示例中,我们定义了一个 convertToUpperCase 方法,它接受一个字符串和一个 Function 参数,用于将输入字符串转换为大写。在 main 方法中,我们通过传递一个 Function 实现来执行转换操作。

字符串长度映射
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FunctionExample {

    public static List<Integer> mapStringLengths(List<String> list, Function<String, Integer> function) {
        return list.stream()
                .map(function)
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        List<String> strings = List.of("apple", "banana", "cherry", "date");
        List<Integer> lengths = mapStringLengths(strings, str -> str.length());
        System.out.println(lengths);
    }
}

在这个示例中,我们定义了一个 mapStringLengths 方法,它接受一个字符串列表和一个 Function 参数,用于将输入字符串映射为它们的长度。通过使用 map 操作,我们在列表中的每个字符串上执行了长度映射。

Supplier

函数式接口 Supplier 在 Java 中用于表示一个不接受参数但产生一个结果的操作。它通常用于延迟计算,只在需要时才执行操作并生成结果。

Supplier 函数式接口

Supplier 接口定义了一个名为 get 的抽象方法,用于获取一个结果。这个接口用于表示一个无参操作,只产生结果。

javaCopy code
@FunctionalInterface
public interface Supplier<T> {
    T get();
}

在上述定义中,T 表示结果的类型

基于 Supplier 进行延迟计算

随机数生成
import java.util.Random;
import java.util.function.Supplier;

public class SupplierExample {

    public static int generateRandomNumber(Supplier<Integer> supplier) {
        return supplier.get();
    }

    public static void main(String[] args) {
        Supplier<Integer> randomSupplier = () -> new Random().nextInt(100);
        int randomNumber = generateRandomNumber(randomSupplier);
        System.out.println("Random number: " + randomNumber);
    }
}

在这个示例中,我们定义了一个 generateRandomNumber 方法,它接受一个 Supplier 参数,并通过调用 get 方法获取随机数。在 main 方法中,我们创建了一个随机数生成的 Supplier,然后将它传递给 generateRandomNumber 方法来获取随机数。

延迟初始化
import java.util.function.Supplier;

public class SupplierExample {

    private String expensiveResource = null;

    public String getExpensiveResource(Supplier<String> supplier) {
        if (expensiveResource == null) {
            expensiveResource = supplier.get();
        }
        return expensiveResource;
    }

    public static void main(String[] args) {
        Supplier<String> resourceSupplier = () -> {
            System.out.println("Initializing expensive resource...");
            return "Expensive Resource";
        };
        SupplierExample example = new SupplierExample();
        System.out.println(example.getExpensiveResource(resourceSupplier));
        System.out.println(example.getExpensiveResource(resourceSupplier));
    }
}

在这个示例中,我们定义了一个 getExpensiveResource 方法,它接受一个 Supplier 参数,并使用延迟初始化的方式获取昂贵的资源。在 main 方法中,我们创建了一个资源初始化的 Supplier,然后多次调用 getExpensiveResource 方法,观察只有在需要时才会初始化资源。

标签:Java,函数,自定义,List,接口,Supplier,方法,public
From: https://blog.51cto.com/u_14129797/8202924

相关文章

  • 解锁多核处理器的力量:探索数据并行化在 Java 8 Stream 中的应用
    在Java8中引入的Stream为集合数据的处理带来了现代化的方式,而数据并行化则进一步提升了处理速度,充分发挥了多核处理器的优势。本篇博客将详细介绍数据并行化在Java8Stream中的应用,以及如何利用并行流处理大量数据。什么是数据并行化数据并行化是指将任务分解成多个子任务,......
  • (十)Robot Framework之处理接口响应
    处理响应数据1.获得响应正文${响应结果.content}二进制编码${响应结果.text}unicode码形式的正文${响应结果.content.decode("utf-8")}转码为utf-82.json格式${json变量} tojson ${响应结果.content} pretty_print=True获取json中的的项(相当于正则提取器)${变......
  • 自定义xunit测试用例的执行顺序
    有的时候我们会对程序进行单元测试,为了测试的效果以及后期的维护,我一般会将各个测试拆开,根据需要测试的类分到各个类型中,不过在实际操作的时候就出现了一些意想不到的问题,各个测试的执行是乱序的,按照我自己写测试的习惯,假如我需要测试新写的增删改查的功能,我会将......
  • SpringBoot通过自定义注解+反射机制比较两个对象不同的属性值
    publicclassFieldComparisonUtil{/**•直接返回一个新的对象,并且对象的值只有被修改的部分••@paramold•@paramsource•@paramisParent•@paramtarget目标对象•@return/**•@paramold进行属性比较的原始数据•@paramsource进行属性比......
  • Java 获取自定义注解 字段值 及 注解值
    自定义注解packagecom.jianmu.bean.annotation;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/**[email protected]......
  • java随机数
    在Java中生成随机数可以使用java.util.Random类或者java.lang.Math类的静态方法,也可以使用Java8引入的java.util.concurrent.ThreadLocalRandom类。参考文章:java怎么产生随机数使用java.util.Random类:importjava.util.Random;publicclassMain{publicstaticvoid......
  • java数组最大值
    参考文章:java数组求最大值在Java中,你可以通过遍历数组元素来找到数组中的最大值。以下是两种常见的方法:使用循环遍历数组publicclassMain{publicstaticvoidmain(String[]args){int[]array={10,5,8,2,7};//假设数组的第一个元素是最大......
  • Shell系列---【常用脚本之---java启动脚本:run.sh】
    run.sh#!/bin/sh-lapplication=node_exporterPORT=1888CUR_IP=${hostname-I|awk'{print$1}'}command="/opt/app/middles/node_exporter/node_exporter--web.listen-address=:$PORT"#停止stop(){ echo"=============================......
  • Java设计模式之桥接模式
    桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。假如你有一个几何形状(Shape)类,从它能扩展出两个子类:圆形(Circle)和方形(Square)。你希望对这样的类层次结构进行扩展以使其包含颜色,所......
  • java设计模式之适配器模式
    定义将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。......