首页 > 编程语言 >Java8 Consumer、Supplier、Predicate、Function

Java8 Consumer、Supplier、Predicate、Function

时间:2024-06-23 21:53:35浏览次数:32  
标签:Function Predicate java accept util Supplier Consumer public

今天我们还讲讲Consumer、Supplier、Predicate、Function这几个接口的用法,在 Java8 的用法当中,这几个接口虽然没有明目张胆的使用,但是,却是润物细无声的。为什么这么说呢?这几个接口都在 java.util.function 包下的,分别是Consumer(消费型)、supplier(供给型)、predicate(谓词型)、function(功能性),相信有了后面的解释,你应该非常清楚这个接口的功能了。那么,下面,我们从具体的应用场景来讲讲这个接口的用法!

vConsumer

Java Consumer接口来自Java 8中引入的 java.util.function包。
Consumer是一个功能接口,用来作为lambda表达式或方法引用的任务目标(传递一个参数执行指定的方法)。

Consumer的功能接口是一个接受单一参数并且不返回任何结果的操作。

Consumer的功能方法是accept(T t)。

Consumer具有以下方法。

1. accept : 这是Consumer功能接口的功能方法。accept 方法对给定的参数进行这一操作。

2. andThen : 此方法返回一个组合的Consumer,该Consumer先执行原始的Consumer操作,然后按照从左到右的顺序执行给定的andThen操作。

功能方法:accept

功能方法accept在功能接口Consumer中的定义

void accept(T t) 

使用示例

ConsumerAccept.java

import java.util.function.Consumer;

public class ConsumerAccept {
  public static void main(String[] args) {
    Consumer<String> nameConsumer = s -> System.out.println(s); 
    
    nameConsumer.accept("Mahesh");
    nameConsumer.accept("Krishna");
  }
} 

输出

Mahesh
Krishna 

使用Lambda表达式创建Consumer
可以使用lambda表达式创建Consumer。

例1 基础类型操作
在我们的示例中,我们将使用lambda表达式在此处创建两个Consumer。

一个用于将数字添加到列表的方法,如果数字为奇数,则将添加到具有奇数的列表中;如果数字为偶数,则将其添加到具有偶数的另一个列表中。

ConsumerLambda1.java

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

public class ConsumerLambda1 {
  public static void main(String[] args) {
    List<Integer> oddList = new ArrayList<>();
    List<Integer> evenList = new ArrayList<>();
    
    Consumer<Integer> storeNumber = n -> {
       if (n % 2 == 0) {
         evenList.add(n);
       } else {
         oddList.add(n);
       }
    };
    
    Consumer<List<Integer>> printList = list -> list.forEach(n -> System.out.println(n));
    
    storeNumber.accept(10);
    storeNumber.accept(15);
    storeNumber.accept(25);
    storeNumber.accept(30);
    
    System.out.println("--- Odd number ---");
    
    printList.accept(oddList);
    
    System.out.println("--- Even number ---");
    
    printList.accept(evenList);
  }
} 

输出结果

--- Odd number ---
15
25
--- Even number ---
10
30 

例2 对象类型操作

我们将使用lambda表达式创建一个Consumer,它将决定并显示一个公民在选举中是否可以投票的数据。

ConsumerLambda2.java

import java.util.function.Consumer;

public class ConsumerLambda2 {
  public static void main(String[] args) {
     Consumer<Citizen> electionConsumer = c -> {
       if (c.getAge() < 18) {
         System.out.println(c.getName() + " is not eligible to vote.");
       } else {
         System.out.println(c.getName() + " can vote.");
       }
     };
     
     electionConsumer.accept(new Citizen("Ritesh", 15));
     
     electionConsumer.accept(new Citizen("Shreya", 20));
  }
}

class Citizen {
  private String name;
  private int age;

  public Citizen(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public int getAge() {
    return age;
  }
} 

输出结果

Ritesh is not eligible to vote.
Shreya can vote. 

使用方法引用创建Consumer
Consumer可以使用方法引用来创建。

在我们的例子中,我们有一个有两个方法的实用类Utility,其中一个方法将替换Map中的值,第二个方法显示Map中的数据。我们将使用方法引用来创建Consumer。

ConsumerMethodRef.java

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

public class ConsumerMethodRef {
  public static void main(String[] args) {
    Map<Integer, String> persons = new HashMap<Integer, String>();
    persons.put(101, "Mahesh");
    persons.put(102, "Krishna");

    Consumer<Map<Integer, String>> updatePersons = Utility::updateData;

    Consumer<Map<Integer, String>> displayPersons = Utility::displayData;

    updatePersons.accept(persons);

    displayPersons.accept(persons);
  }
}

class Utility {
  static void updateData(Map<Integer, String> persons) {
    persons.replaceAll((k, v) -> "Shree ".concat(v));
  }

  static void displayData(Map<Integer, String> persons) {
    for (Map.Entry<Integer, String> entry : persons.entrySet()) {
      System.out.println(entry.getKey() + " - " + entry.getValue());
    }
  }
} 

输出结果

101 - Shree Mahesh
102 - Shree Krishna 

使用andThen方法

Java文档中andThen方法声明。

default Consumer<T> andThen(Consumer<? super T> after) 
  1. 这个方法返回一个组合的Consumer,先执行当前Consumer操作,然后再执行afterConsumer操作。
  2. 如果在此操作或操作之后有异常,则将其中继到当前组合操作。
  3. 如果这个操作出现异常,那么后面的操作将不会被执行。

例1 简单拼接Consumer

我们的示例中有两个Consumer

首先将执行squareConsumer,然后将执行printConsumer

ConsumerAndThen1.java

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

public class ConsumerAndThen1 {
  public static void main(String[] args) {
    List<Integer> numList = Arrays.asList(3, 4, 5, 6);

    Consumer<List<Integer>> squareConsumer = list -> {
      for (int i = 0; i < list.size(); i++) {
        list.set(i, list.get(i) * list.get(i));
      }
    };

    Consumer<List<Integer>> printConsumer = list -> list.forEach(n -> System.out.println(n));

    squareConsumer.andThen(printConsumer).accept(numList);
  }
} 

 输出

9
16
25
36 

 

例2 多个拼接Consumer

我们多次使用andThen。首先将执行oddNumConsumer,然后将执行evenNumConsumer,然后将执行taskFinishConsumer

ConsumerAndThen2.java

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

public class ConsumerAndThen2 {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(12, 13, 14, 15, 16, 17);

    Consumer<List<Integer>> oddNumConsumer = MyNumber::printOddNum;

    Consumer<List<Integer>> evenNumConsumer = MyNumber::printEvenNum;

    Consumer<List<Integer>> taskFinishConsumer = MyNumber::taskFinishMsg;

    oddNumConsumer.andThen(evenNumConsumer).andThen(taskFinishConsumer).accept(list);
  }
}

class MyNumber {
  static void printOddNum(List<Integer> myNumbers) {
    System.out.println("--- odd numbers ---");
    myNumbers.forEach(n -> {
      if (n % 2 == 1) {
        System.out.print(n + " ");
      }
    });
  }

  static void printEvenNum(List<Integer> myNumbers) {
    System.out.println("\n--- even numbers ---");
    myNumbers.forEach(n -> {
      if (n % 2 == 0) {
        System.out.print(n + " ");
      }
    });
  }

  static void taskFinishMsg(List<Integer> myNumbers) {
    System.out.println("\nTotal " + myNumbers.size() + " number processed.");
  }
} 

输出结果

--- odd numbers ---
13 15 17 
--- even numbers ---
12 14 16 
Total 6 number processed. 

vSupplier

Java 8引入了函数式接口 Supplier 是一个无参数的函数式接口,它不接受任何输入参数,但可以返回一个结果。它定义了一个名为 get() 的抽象方法,用于获取结果。

下面是Supplier<T>接口的定义:

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

在函数式编程中, Supplier 接口常用于延迟计算或惰性求值。它可以用来表示一个供应商或提供者,用于生成或获取数据。当需要获取数据时,可以调用 Supplier 的 get() 方法来获取结果。使用 Supplier 接口的主要优势之一是它可以与Java 8的新特性lambda表达式结合使用。通过lambda表达式,可以以更简洁和易读的方式定义 Supplier 对象。

下面是一个使用Supplier接口的示例:

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        // 使用lambda表达式创建Supplier对象
        Supplier<String> supplier = () -> "你好,世界!";
        String result = supplier.get();
        // 调用get()方法获取结果
        System.out.println(result);
    }
}
// 输出:你好,世界!

在上面的示例中,我们使用lambda表达式创建了一个返回字符串"Hello, World!"的 Supplier 对象。然后,我们调用了 get() 方法来获取结果,并将其打印到控制台上。
除了简单的返回固定值之外, Supplier 接口还可以用于生成随机数、读取文件、从数据库中获取数据等各种场景。通过实现 Supplier 接口的自定义类,我们可以根据具体需求来生成或获取数据。

以下是其他常见用法示例:
1. 提供随机数生成器:

Supplier<Integer> randomGenerator = () -> new Random().nextInt();
int randomNumber = randomGenerator.get();

2. 延迟加载资源:

Supplier<DatabaseConnection> connectionSupplier = () -> new DatabaseConnection();
DatabaseConnection connection = connectionSupplier.get();

3. 惰性初始化对象:

Supplier<ExpensiveObject> lazyInitializer = ExpensiveObject::new;
ExpensiveObject object = lazyInitializer.get();

总结一下,Java 8的函数式接口 Supplier 用于表示一个供应商或提供者,它不接受任何输入参数,但可以返回一个结果。它可以与lambda表达式结合使用,用于延迟计算或惰性求值。

vPredicate

Java 8中引入了Predicate功能接口。Java Predicate表示一个参数的谓词。Predicate是一个布尔值的函数。Java Predicate是一个功能接口,属于java.util.function包。Predicate的功能方法是test(T t)。Predicate的其他方法是isEqual、and、or、negate和not。not方法在Java 11中被引入。

        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }else{
                    return false;
                }
            }
        };
        System.out.println(predicate.test(6)); // true
        Predicate<Integer> predicate2 = (t) -> t > 5;
        System.out.println(predicate2.test(1)); // false
        Predicate<String> isUserNameValid = u -> u != null && u.length() > 5 && u.length() < 10;
        System.out.println(isUserNameValid.test("Mahesh")); // true

vFunction

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。且用@Function标签标记的接口。Java8 新增加的函数接口在 java.util.function 包下,它包含了很多类,用来支持 Java 的函数式编程。

Function< T , R >

函数产生给定数据类型的结果,并接受一个参数作为给定数据类型,T参数类型,R是结果类型。Function 接口是一个功能型接口,它的一个作用就是转换作用,将输入数据转换成另一种形式的输出数据。

        Function<Integer,String> ob = f1 -> "Age:"+f1;
        System.out.println(ob.apply(20)); // 输出:Age:20
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();//获取每个字符串的长度,并且返回
            }
        };

        Stream<String> stream = Stream.of("qqq", "wwwww", "eeeeee");
        Stream<Integer> stream1 = stream.map(function);
        stream1.forEach(System.out::println);

其他参考/学习资料:

v源码地址

https://github.com/toutouge/javademosecond/tree/master/hellolearn


作  者:请叫我头头哥
出  处:http://www.cnblogs.com/toutou/
关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

标签:Function,Predicate,java,accept,util,Supplier,Consumer,public
From: https://www.cnblogs.com/toutou/p/java_Function_Consumer.html

相关文章

  • def __init__(self,parameterlist)初始化方法和def __functionName__(self,parameterl
    问题描述:def__init__(self,parameterlist)初始化方法和def__functionName__(self,parameterlist)实例方法,其中functionName是具体方法的名字,比如表示奔跑、或者狗叫的方法。对于上面这两种方法有什么区别?问题解答:在Python类中,__init__方法和其他实例方法(如__functionName_......
  • a regrex for function title
    正则表达式简明扼要,一行代码就能实现挺复杂的功能。deftitle(s):returnre.sub(rb"[A-Za-z]+('[A-Za-z]+)?",lambdamo:mo.group(0)[0:1].upper()+lambdamo:mo.group(0)[1:].lower(),s)解释正则表达式"[A-Za-z]+('[A-Za-z]+)?"的作用是匹配一个或多个英文字母(大小写......
  • RAG与LLM原理及实践(2)--- RAG结合LLM function调用的原理及落地实践
    花一点时间继续写下,RAG结合LLM。通过上一篇文章你应该知道为什么RAG要结合LLM,或者说为什么LLM要结合RAG使得LLM更强大,特别是当LLM应用在人机对话等方面的时候。只要涉及一问一答,并通过上下文继续丰富对话,就会涉及到他。这个是看事情的两个维度。就像是买钟送电池还是买电池送......
  • puppeteer exposeFunction 方法简单试用
    以下简单演示下puppeteerexposeFunction的使用环境准备基于browserlessdocker-composeversion:"3"services:nginx:image:nginx:alpinevolumes:-./index.html:/usr/share/nginx/html/index.htmlports:-"80......
  • ERROR TypeError: this.nzData.slice is not a function
    原文链接:ERRORTypeError:this.nzData.sliceisnotafunction–每天进步一点点(longkui.site) 使用angular+ngzorro的nz-table渲染表格的时候报错:ERRORTypeError:this.nzData.sliceisnotafunction我的html部分代码如下:<nz-table#basicTable2[nzData]="lis......
  • Vitis HLS 学习笔记--函数例化(Function Instantiation)
    目录1.简介2.功能分析3.示例分析3.1不使用 FUNCTION_INSTANTIATE3.2使用 FUNCTION_INSTANTIATE4.总结1.简介函数例化(FunctionInstantiation)是VitisHLS中的一个高级优化技术。它允许开发者在保持函数层次结构的同时,对函数的特定实例进行局部优化。如果函......
  • python调用智能合约代码,BadFunctionCallOutput 怎么解决
    目录桌面应用使用QT5开发的,可以看看我的QT5文章BadFunctionCallOutput 怎么解决我的原因是智能合约地址填写错误python智能合约基础应用如何使用remix编写solidity智能合约并部署上链在哪进行合约部署,合约部署步骤Remix怎么复制abi和address​编辑这个ABI对应最简......
  • Java - function
     Java-Assignment04(100pts)InstructionsWriteeachexerciseinitsownmethod.Uncommentthefunctioncallsinmain()toactivateeachexercise.Referto"Assignment01"ifnecessary.Foreachexercise,usecommentstowritepseudocodew......
  • Codeforces Round 952 (Div. 4) G. D-Function(思维)
    Problem-G-Codeforces思维题,推出公式用等比数列求和做一下。1#defineIOstd::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)2#definebug2(x,y)cout<<#x<<"is"<<x<<""<<#y<<"is"<<y<<end......
  • JDK8新特性【接口新特征、lambda语法、Supplier、Consumer、Function、Predicate】
    目录一、关于接口的新特性1.1jdk1.8之前的接口重要特性1.2JDK8以后代码演示1.3总结通过代码演示发现作用二、Lambda表达式[重点]2.1将匿名内部类写法改写为lambda写法2.2语法特点能够写成lambda形式的的前提语法特征代码演示深入理解lambda2.3总结三、函数......