Java 8-函数式接口

news2024/9/17 8:23:30

目录

一、概述

二、 函数式接口作为方法的参数

三、函数式接口作为方法的返回值

四、 常用的函数式接口

简单总结

简单示例

4.1 Consumer接口

简单案例

自我练习

实际应用场景

多线程处理

4.2 Supplier接口

简单案例

自我练习

实际应用场景

配置管理

4.3 Function接口

简单案例

自我练习

实际应用场景

数据转换器

数据映射

4.4 Predicate接口

简单案例

自我练习

实际应用场景

权限验证

4.5 综合应用案例

五、Lambda 应用

1.Consumer (消费型接口)

2.Supplier (供给型接口)

3..Function (函数型接口)

4..Predicate (断言型接口)


一、概述

定义:有且仅有一个抽象方法的接口

  • Java中函数式编程体现:Lambda表达式

  • 函数式接口就是可以适用于Lambda使用的接口

    • 只有确保接口中仅有一个抽象方法,Java中的Lambda才能顺利地进行推导

如何检测一个接口是不是函数式接口?

  • @Functionallnterface

  • 放在 接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败

注意:

我们自己定义函数式接口的时候,@Functionallnterface是可以选的,就算我们不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解,虽然这不是强制性的,但使用它可以避免无意中添加额外的方法,从而破坏函数式接口的特性。

核心概念

  • 函数式接口:具有且仅有一个抽象方法的接口。

  • Lambda表达式:一种匿名函数,可以用来替代只有单一方法的类的实例化。

  • 方法引用:如果Lambda表达式只是简单地引用已有方法,那么可以用方法引用代替Lambda表达式。

二、 函数式接口作为方法的参数

需求

  • 定义一个类(RunnableDemo),在类中提供两个方法

    • 一个方法是:startThread(Runnable r) 方法参数Runnabler是一个函数式接口

    • 一个方法是主方法,在主方法中调用startThread方法

如果方法的参数是一个函数式接口,我们可以用Lambda表达式作为参数传递

startThread(()->System.out.println(Thread.currentThread().getName()+“线程启动了”));
public class RunnableDemo {
    public static void main(String[] args) {
        // Lambda表达式作为参数传递 
        startThread(()-> System.out.println(Thread.currentThread().getName()+"线程启动了"));
    }
​
    private static void startThread(Runnable r){
        new Thread(r).start();
    }
}

三、函数式接口作为方法的返回值

需求

  • 定义一个类(ComparatorDemo),在类中提供两个方法

    • 一个方法是:Comparator< String > getComparator() 方法返回值Comparator是一个函数式接口

    • 一个方法是主方法,在主方法中调用getComparator方法

如果一个方法的返回值是一个函数式接口,我们可以把一个Lambda表达式作为结果返回

private static Comparator<String> getComparator() {
    // 定义了一个接受两个参数 s1 和 s2 的函数,这两个参数都是字符串类型。计算 s1 的长度减去 s2 的长度,并返回结果
    return (s1, s2) -> s1.length() - s2.length();
}


package com.geeksss.excel.model;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
​
/**
 * ComparatorDemo 使用自定义比较器对字符串列表进行排序。
 */
public class ComparatorDemo {
    /**
     * 主函数执行字符串列表的排序操作。
     * @param args 命令行参数,未使用。
     */
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("cccc");
        list.add("aa");
        list.add("b");
        list.add("ddd");
        
        System.out.println("排序前" + list);
        // 使用自定义比较器对列表进行排序。
        Collections.sort(list, getComparator());
        System.out.println("排序后" + list);
    }
    
    /**
     * 使用Lambda表达式创建并返回Comparator实例
     * 获取一个比较器实例,该比较器按字符串长度进行排序。
     *
     *  Lambda表达式: (s1, s2) -> s1.length() - s2.length()
     *  这个表达式定义了一个比较规则,根据字符串的长度进行比较
     *  当s1.length() > s2.length(),返回正值,表示s1在排序中应该位于s2之后,s1比s2长
     *  当s1.length() < s2.length(),返回负值,表示s1在排序中应该位于s2之前,s1比s2短
     *  当s1.length() == s2.length(),返回0,表示两个字符串长度相等,保持原顺序,s1与s2一样长
     *
     *  方法的返回值是一个函数式接口,把一个Lambda表达式作为返回结果
     * @return 返回一个 Comparator 实例,用于按照字符串长度进行排序。
     */
    private static Comparator<String> getComparator() {
        // 使用 Lambda 表达式定义比较逻辑:按字符串长度进行比较。
        // 使用匿名内部类实现
//        return new Comparator<String>() {
//            @Override
//            public int compare(String s1, String s2) {
//                return s1.length()-s2.length();
//            }
//        };
        
        // Lambda 表达式写法,等效于上述匿名内部类实现。
        return (s1, s2) -> s1.length() - s2.length();
    }
​
​
}
​
 

排序前[cccc, aaaa, b, ddd] 排序后[b, ddd, cccc, aaaa]

四、 常用的函数式接口

Java 8在java.util.function包下预定义了大量的函数式接口供我们使用,重点学习下面4个接口

简单总结
  • Consumer<T>:接收一个参数,但没有返回值。

    • 常用于遍历数据结构,执行副作用操作,如打印或更新状态

  • Supplier<T>:不接收参数,返回一个结果。

    • 可以用于创建延迟初始化的对象,或获取数据源的值

  • Function<T, R>:接收一个参数并返回一个结果。

    • 可以用于数据转换或映射

  • Predicate<T>:接收一个参数并返回一个布尔值。

    • 通常用于数据过滤

简单示例
import java.util.function.*;
​
public class FunctionalInterfaceExample {
​
    public static void main(String[] args) {
         // Consumer 示例
        Consumer<String> printUpperCase = System.out::println;
        printUpperCase.accept("HELLO"); // 输出 HELLO
        
        // Supplier 示例
        Supplier<Double> randomSupplier = Math::random;
        System.out.println(randomSupplier.get()); // 输出一个随机数
        
         // Function 示例
        Function<String, Integer> stringToInt = Integer::parseInt;
        System.out.println(stringToInt.apply("123")); // 输出 123
        
        // Predicate 示例
        Predicate<Integer> isEven = x -> x % 2 == 0;
        System.out.println(isEven.test(4)); // 输出 true
       
    }
}
​
4.1 Consumer接口

Consumer是一个消费型接口,它接受一个参数但不返回任何值。它常用于对集合中的元素执行某种操作,如打印或修改数据。

Consumer< T >:包含两个方法

  • void accept(T t):对给定的参数执行此操作

  • default Consumer < T > andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作

  • Consumer< T >接口也被称为消费型接口,它消费的数据类型由泛型指定

简单案例
package com.geeksss.excel.model;
​
import java.util.function.Consumer;
​
/**
 * 消费者示例类,使用Consumer接口处理字符串。
 */
public class ConsumerDemo {
    
    public static void main(String[] args) {
        // 单个消费者处理字符串
        operatorString("张三", (s) -> System.out.println(s));
        
        // 两个消费者依次处理字符串
        operatorString("张三", (s) -> System.out.println(s), (s) -> System.out.println(new StringBuilder(s).reverse().toString()));
    }
    
    /**
     * 接受一个字符串并应用一个消费者。
     * @param name 要处理的字符串
     * @param con 字符串的消费者
     */
    // 定义一个方法,消费一个字符串数据
    private static void operatorString(String name, Consumer<String> con) {
        con.accept(name);
    }
    
    /**
     * 接受一个字符串并依次应用两个消费者。
     * @param name 要处理的字符串
     * @param con1 第一个字符串消费者
     * @param con2 第二个字符串消费者
     */
    // 定义一个方法,用不同的方式消费同一个字符串两次
    private static void operatorString(String name, Consumer<String> con1, Consumer<String> con2) {
        // 通过andThen方法将两个消费者串联起来,形成一个消费链
        // 返回一个组合的Consumer
        con1.andThen(con2).accept(name);
    }
    // 张三
    // 张三
    // 三张
}
自我练习
  • String[] strArray = {“张三,30”, “李四,21”, “王五,18”};

  • 字符串数组中有多条信息,按照格式:

    • 把打印姓名的动作,作为第一个Consumer接口的Lambda实例

    • 把打印年龄的动作,作为第二个Consumer接口的Lambda实例

    • 将两个Consumer接口按照顺序组合到一起使用

package com.geeksss.excel.model;
​
import java.util.Arrays;
import java.util.function.Consumer;
​
/**
 * @author zhumq
 * @date 2024/7/30 22:27
 */
public class ConsumerTest {
  
    public static void main(String[] args) {
        String[] strArray = {"张三,30", "李四,21", "王五,18"};
        // 使用operatorString方法处理字符串数组,分别输出原字符串和分割后的数组
        operatorString(strArray, (s) -> System.out.println(s), (s) -> System.out.println(Arrays.toString(s.split(","))));
    }
    
    /**
     * 对字符串数组中的每个元素应用两个消费者操作:首先执行第一个消费者,然后执行第二个消费者。
     *
     * @param strArray 字符串数组
     * @param con1     第一个字符串消费者
     * @param con2     第二个字符串消费者
     */
    public static void operatorString(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
        for (String str : strArray) {
            // 通过andThen方法将两个消费者串联起来,形成一个消费链
            con1.andThen(con2).accept(str);
        }
    }
    // 张三,30
    // [张三, 30]
    // 李四,21
    // [李四, 21]
    // 王五,18
    // [王五, 18]
}
实际应用场景
多线程处理

Consumer接口在多线程环境中非常有用,可以用于并行处理数据集中的每个元素,例如在异步任务中处理数据。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
​
public class MultiThreadedProcessing {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        Consumer<String> processTask = task -> {
            System.out.println("Processing task '" + task + "' on thread " + Thread.currentThread().getName());
            // 这里可以是任务的具体处理逻辑
        };
​
        for (int i = 0; i < 10; i++) {
            String task = "Task-" + i;
            executor.submit(() -> processTask.accept(task));
        }
​
        executor.shutdown();
    }
}
​

4.2 Supplier<T>接口

Supplier< T >:包含一个无参的方法

  • T get():获得结果

  • 该方法不需要参数,他会按照某种实现逻辑返回一个数据(由Lambda表达式实现)

  • Supplier< T >接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用

简单案例
import java.util.function.Supplier;

public class SupplierDemo {
    public static void main(String[] args) {
        String s = getString(()->"张三");
        int i = getInteger(()->18);

        System.out.println(s+","+i);
    }

    //定义一个方法,返回一个字符串数据
    private static String getString(Supplier<String> sup){
        return sup.get();
    }

    //定义一个方法,返回一个整数数据
    private static Integer getInteger(Supplier<Integer> sup){
        return sup.get();
    }
}
自我练习
  • 定义一个类(SupplierTest),在类中提供两个方法

    • 一个方法是:int getMax(Supplier< Integer > sup) 用于返回一个int数组中的最大值

    • 一个方法是主方法,在主方法中调用getMax方法

package com.geeksss.excel.model;

import java.util.function.Supplier;
/**
 * SupplierTest 使用 Supplier 接口来获取一个值
 */
public class SupplierTest {

    
    public static void main(String[] args) {
        // 初始化一个整型数组
        int[] i = {3,75,32,76,98,42};
        
        // 使用 getMax 方法来获取数组中的最大值,传递一个 Supplier 实现来计算最大值
        int maxValue = getMax(()->{
            int max = i[0];
            // 遍历数组找到最大值
            for (int j = 1; j < i.length; j++) {
                if(i[j]>max){
                    max = i[j];
                }
            }
            return max;
        });
        
        System.out.println(maxValue);
    }
    
    /**
     * 使用 Supplier 获取一个值。
     * @param sup 提供值的 Supplier 实例
     * @return 由 Supplier 提供的值
     */
    private static Integer getMax(Supplier<Integer> sup){
        return sup.get();
    }
}
实际应用场景
配置管理

Supplier可以用于配置管理,例如延迟加载配置项,确保配置在首次请求时才被读取,从而节省资源。

import java.util.function.Supplier;

public class ConfigurationManager {
    private Supplier<String> configSupplier;

    public ConfigurationManager(Supplier<String> configSupplier) {
        this.configSupplier = configSupplier;
    }

    public String getConfig() {
        return configSupplier.get();
    }
}

// 使用示例
public class ConfigLoader {
    public static void main(String[] args) {
        ConfigurationManager manager = new ConfigurationManager(() -> {
            // 模拟从文件或网络加载配置
            return "Loaded configuration";
        });

        System.out.println(manager.getConfig());
    }
}

4.3 Function接口

Runction<T,R>:常用的两个方法

  • R apply(T t):将此函数应用于给定的参数

  • default< V >:Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果

  • Function<T,R>:接口通常用于对参数进行处理转换,然后返回一个新值(处理逻辑由Lambda表达式实现)

简单案例
import java.util.function.Function;
 
public class FunctionExample {
 
    public static void main(String[] args) {
        // 创建一个 Function 对象,它接受一个 String 类型的参数并返回一个 Integer 类型的结果, 引用 String::length,是 Lambda 表达式的简洁版
        Function<String, Integer> stringLengthFunction = String::length;

        // 使用 apply 方法调用 Function 对象,传入一个具体的 String 参数。
        int length = stringLengthFunction.apply("Hello, World!");

        System.out.println("The length of the string is: " + length);
    }
}
自我练习
package com.dev.springBootDemo;

import java.util.function.Function;

/**
 * FunctionTest 不同类型的转换函数的使用
 */
public class FunctionTest {
 
    public static void main(String[] args) {
        // 字符串转整数并打印
        convert("18", s -> Integer.parseInt(s));
        // 整数加法运算后转字符串并打印
        convert(20, integer -> String.valueOf(integer + 18));
        // 字符串转整数,整数加法运算后转字符串并打印
        convert("245", s -> Integer.parseInt(s), integer -> String.valueOf(integer + 18));
    }
    
    /**
     * 将字符串转换为整数并打印。
     * @param s 要转换的字符串
     * @param fun 字符串到整数的转换函数
     */
    // 定义一个方法,把一个字符串转换成int类型,在控制台输出
    private static void convert(String s, Function<String, Integer> fun) {
        int i = fun.apply(s);
        System.out.println(i);
    }
    
    /**
     * 将整数进行运算后转换为字符串并打印。
     * @param i 要转换的整数
     * @param fun 整数到字符串的转换函数
     */
    // 定义一个方法,把int类型数据加上一个整数之后,转换为字符串在控制台输出
    private static void convert(int i, Function<Integer, String> fun) {
        String s = fun.apply(i);
        System.out.println(s);
    }
    
    /**
     * 将字符串转换为整数,进行运算后再转换为字符串并打印。
     * @param s 要转换的字符串
     * @param fun1 字符串到整数的转换函数
     * @param fun2 整数到字符串的转换函数
     */
    // 定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数后,转换成字符串在控制台输出
    private static void convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
        String s1 = fun2.apply(fun1.apply(s));
        System.out.println(s1);
    }
}

实际应用场景
数据转换器

假设正在开发一个系统,需要处理来自不同来源的数据,这些数据可能以不同的格式存储。可以使用 Function 接口来创建转换器,将这些数据转换成统一的格式。例如,可能有一个函数将 JSON 字符串转换为对象,另一个函数将 XML 转换为对象,等等。这样,可以在系统中重用这些,提高代码的可读性和可维护性。

package com.dev.springBootDemo;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.gson.Gson;

import java.util.function.Function;
/**
 * 数据转换器类,用于根据提供的转换函数将原始数据转换为特定类型。
 */
public class DataConverter {
    
    /**
     * 使用提供的转换函数将原始数据转换为指定类型。
     *
     * @param rawData 原始数据,以字符串形式表示。
     * @param converter 转换函数,用于将原始数据字符串转换为目标类型T。
     * @param <T> 目标数据类型。
     * @return 转换后的数据对象。
     */
    // 定义一个通用的转换函数,它接受一个 String 类型的原始数据和一个 Function 对象,
    // 该 Function 对象负责将原始数据转换为目标类型 T。
    public static <T> T convertData(String rawData, Function<String, T> converter) {
        return converter.apply(rawData);
    }
    
    public static void main(String[] args) {
        // 假设我们有 JSON 和 XML 数据
        String jsonData = "{\"name\":\"John\", \"age\":30}";
        String xmlData = "<person><name>John</name><age>30</age></person>";
        
        // JSON 转换器
        Function<String, Person> jsonConverter = s -> new Gson().fromJson(s, Person.class);
        
        // XML 转换器
        Function<String, Person> xmlConverter = s -> new XmlMapper().readValue(s, Person.class);
        
        // 使用转换函数将JSON数据转换为Person对象
        Person personFromJson = convertData(jsonData, jsonConverter);
        // 使用转换函数将XML数据转换为Person对象
        Person personFromXml = convertData(xmlData, xmlConverter);
        
        System.out.println(personFromJson);
        System.out.println(personFromXml);
    }
}
数据映射

Function接口在数据映射和转换中扮演重要角色,例如将一种数据类型转换为另一种数据类型。

import java.util.function.Function;

public class DataMapper {
    public static void main(String[] args) {
        Function<String, Integer> parseInteger = Integer::parseInt;
        String input = "123";
        Integer output = parseInteger.apply(input);
        System.out.println("Parsed integer: " + output);
    }
}

4.4 Predicate接口

常用于

Predicate< T >:常用的四个方法

  • boolean test(T t):对给定的参数进行判断,返回一个布尔值(判断逻辑由Lambda表达式实现)

  • default Predicate< T > negate():返回一个逻辑的否定,对应逻辑非

  • default Predicate< T > and():返回一个组合判断,对应短路与

  • default Predicate< T > or():返回一个组合判断,对应短路或

  • isEqual():测试两个参数是否相等

  • Predicate< T >:接口通常用于判断参数是否满足指定的条件

test(T t) 、negate()

简单案例
package com.dev.springBootDemo;

import java.util.function.Predicate;


public class PredicateDemo {
    public static void main(String[] args) {
        // 检查字符串是否等于"张三"
        boolean string = chenkString("张三", s -> s.equals("张三"));
        System.out.println(string);
        
        // 检查字符串长度是否大于8且小于18
        boolean hello = chenkString("hello", s -> s.length() > 8, s -> s.length() < 18);
        System.out.println(hello); // true
    }
    
    /**
     * 使用单个谓词检查字符串是否满足条件。
     *
     * @param s 要检查的字符串
     * @param pre 字符串检查谓词
     * @return 如果字符串满足谓词条件,则返回true;否则返回false。
     */
    // 判定给定的字符串是否满足要求
    // private static boolean chenkString(String s, Predicate<String> pre){
    //     return pre.test(s); // true
    // }
    
    /**
     * 使用单个谓词的否定检查字符串是否不满足条件。
     *
     * @param s 要检查的字符串
     * @param pre 字符串检查谓词
     * @return 如果字符串不满足谓词条件,则返回true;否则返回false。
     */
    private static boolean chenkString(String s, Predicate<String> pre){
        return pre.negate().test(s); // false
    }
    
    /**
     * 使用两个谓词的逻辑与检查字符串是否同时满足两个条件。
     *
     * @param s 要检查的字符串
     * @param pre 第一个字符串检查谓词
     * @param pre1 第二个字符串检查谓词
     * @return 如果字符串同时满足两个谓词条件,则返回true;否则返回false。
     */
    // private static boolean chenkString(String s, Predicate<String> pre, Predicate<String> pre1){
    //     return pre.and(pre1).test(s); // false
    // }java
    /**
     * 使用两个谓词的逻辑或检查字符串是否满足其中一个条件。
     *
     * @param s 要检查的字符串
     * @param pre 第一个字符串检查谓词
     * @param pre1 第二个字符串检查谓词
     * @return 如果字符串满足两个谓词中的任何一个,则返回true;否则返回false。
     */
    private static boolean chenkString(String s, Predicate<String> pre, Predicate<String> pre1){
        return pre.or(pre1).test(s); // true
    }
}
自我练习
  • String[] strArray = {“张三,30”, “李四,21”, “王五,18”};

  • 字符串数组中由多条信息,请通过Predicate接口的拼装将符合要求的字符串筛选到集合Arraylist中,并遍历ArrayList集合

  • 同时满足如下:姓名长度大于1,年龄大于20

  • 分析

    • 有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断

    • 必须同时满足两个条件,所以可以使用and方法连接两个判断条件

package com.dev.springBootDemo;

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


/**
 * 消费者测试类,使用自定义过滤函数筛选数据。
 */
public class PredicateTest {
 
    public static void main(String[] args) {
        // 初始化一个字符串数组,包含姓名和年龄信息。
        String[] strArray = {
                "张三,30", "李四,21", "王五,18"
        };
        // 使用myFilter方法筛选出姓名长度大于1且年龄大于20的人名。
        ArrayList<String> arrayList = myFilter(strArray,
                s -> s.split(",")[0].length() > 1,
                s -> Integer.parseInt(s.split(",")[1]) > 20
        );
        // 遍历并打印筛选结果。
        for (String array : arrayList) {
            System.out.println(array);
        }
    }
    
    /**
     * 自定义过滤方法,根据提供的两个Predicate条件对字符串数组进行筛选。
     * 
     * @param strArray 输入的字符串数组,每个元素包含一个姓名和一个数字。
     * @param pre1 第一个过滤条件的Predicate。
     * @param pre2 第二个过滤条件的Predicate。
     * @return 符合所有条件的字符串集合。
     */
    // 通过Predicate接口的拼装将符合要求的字符串筛选到集合Arraylist中
    private static ArrayList<String> myFilter(String[] strArray, Predicate<String> pre1, Predicate<String> pre2) {
        // 初始化一个ArrayList用于存储筛选结果。
        ArrayList<String> array = new ArrayList<>();
        // 遍历输入数组。
        for (String str : strArray) {
            // 如果字符串同时满足pre1和pre2两个条件,则添加到结果集合中。
            if (pre1.and(pre2).test(str)) {
                array.add(str);
            }
        }
        // 返回筛选结果。
        return array;
    }
}
实际应用场景
权限验证

Predicate在权限验证和安全检查中非常有用,例如检查用户是否有访问特定资源的权限。

import java.util.function.Predicate;

public class PermissionChecker {
    public static void main(String[] args) {
        Predicate<String> hasPermission = role -> role.equals("admin");
        String userRole = "admin";

        boolean canAccess = hasPermission.test(userRole);
        System.out.println("Can access: " + canAccess);
    }
}
 
4.5 综合应用案例

使用这些函数式接口来处理一个员工列表,并执行诸如筛选、转换和输出等操作。

假设有一个Employee类,它有name和age属性,想要从员工列表中找出所有年龄超过30岁的员工的名字,并将这些名字转换为大写形式,最后打印出来。

  • Supplier用于初始化一个空的List<String>,这是结果容器。

  • Predicate用于筛选出年龄大于30岁的员工。

  • Function用于将员工对象转换为大写形式的名字。

  • Consumer用于将转换后的大写名字添加到结果列表中。

首先,定义Employee类:

package com.dev.springBootDemo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author zhumq
 * @date 2024/7/30 23:25
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private String name;
    private int age;
}

接下来,使用Predicate, Function, Consumer和Supplier来解决问题:

package com.dev.springBootDemo;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class EmployeeProcessor {

    public static void main(String[] args) {
        // 创建员工列表
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("张三", 35));
        employees.add(new Employee("李四", 28));
        employees.add(new Employee("王五", 42));
        employees.add(new Employee("陈六", 31));

        // 使用Supplier初始化一个空的List<String>,用于存放结果
        Supplier<List<String>> supplier = ArrayList::new;

        // 使用Predicate过滤年龄大于30岁的员工
        Predicate<Employee> predicate = employee -> employee.getAge() > 30;

        // 使用Function将Employee转换为其大写名字
        Function<Employee, String> function = employee -> employee.getName().toUpperCase();

        // 使用Consumer将转换后的名字添加到List中
        Consumer<String> consumer = supplier.get()::add;

        // 执行操作
        List<String> filteredNames = employees.stream()
                .filter(predicate)
                .map(function)
                .collect(Collectors.toList());

        // 使用Consumer打印结果
        filteredNames.forEach(System.out::println);
    }
}

张三 王五 陈六

五、Lambda 应用

1.Consumer (消费型接口)

Consumer用于消费一个对象,常用于Stream的forEach()方法。

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

public class ConsumerExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        // 使用Consumer打印每个名字
        names.forEach(System.out::println);
    }
}
2.Supplier (供给型接口)

Supplier用于生成一个对象,常用于初始化数据源或延迟加载。

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        Supplier<String> helloWorld = () -> "Hello, World!";
        // 使用Supplier获取结果
        System.out.println(helloWorld.get());
    }
}
3..Function (函数型接口)

Function用于将一个类型的数据转换为另一个类型的数据,常用于Stream的map()方法。

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

public class FunctionExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("one", "two", "three");
        // 使用Function将字符串转换为大写
        List<String> upperCaseWords = words.stream().map(String::toUpperCase).toList();
        System.out.println("Upper case words: " + upperCaseWords);
    }
}

4..Predicate (断言型接口)

Predicate用于判断一个对象是否满足某个条件,常用于Stream的filter()方法。

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

public class PredicateExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        // 使用Predicate过滤出偶数
        List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).toList();
        System.out.println("Even numbers: " + evenNumbers);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1960969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UCC5320SCDWVR驱动SIC的功耗计算

驱动功耗可以通过分析器件的电气特性和推荐的电源电压来估算。以下是一些关键信息&#xff0c;用于估算功耗&#xff1a; 电源电流&#xff1a; 输入电源静态电流&#xff08;IVCC1​&#xff09;&#xff1a;最小值为1.67 mA&#xff0c;典型值为2.4 mA。输出电源静态电流&am…

day33

类类型接口 静态属性和静态方法 区分方法就是必须要有 new什么东西 完成什么类 第二种类类型接口 字面量类类型接口 接口继承 接口继承接口 继承多个接口 接口可以继承多个&#xff0c;但是类只能继承一个 接口不能继承对象 接口继承类&#xff0c;仅继承类中对于实…

力扣高频SQL 50题(基础版)第二十六题

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第二十六题1667.修复表中的名字题目说明实现过程准备数据实现方式结果截图总结 力扣高频SQL 50题&#xff08;基础版&#xff09;第二十六题 1667.修复表中的名字 题目说明 表&#xff1a; Users ----------------…

Day7-指针专题二

1. 字符指针与字符串 C语言通过使用字符数组来处理字符串 通常&#xff0c;我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系&#xff0c;它也被用来处理字符串 初始化字符指针是把内存中字符串的首地址赋予指针&#xff0c;并不是把该字符串…

TCP/UDP通信

1、TCP/IP四层模型 TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff0c;传输控制协议/网际协议&#xff09;是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议&#xff0c;而是指一个由FTP、SMTP、TCP、UDP…

【Linux】make/Makefile的理解

1.make是一个命令&#xff0c;makefile是一个文件, 依赖关系和依赖方法. a.快速使用一下 i.创建一个Makefile文件(首字母也可以小写) b.依赖关系和依赖方法 i.依赖关系: 我为什么要帮你? mybin:mytest.c ii.依赖方法: 怎么帮? gcc -o mybin mytest.c make之前要注意先创建…

每期一个小窍门: 使用Gin 与 client-go 操作k8s (中)

本文承接上文 每期一个小窍门: 使用Gin 与 client-go 操作k8s &#xff08;上&#xff09; 后面应该还会有个下 应该是个operator的全程demo 项目结构如下 client.go package clientimport ("k8s.io/client-go/discovery""k8s.io/client-go/kubernetes"…

使用easypoi读取Excel模板

1、只读取一个脚本号Excel2、读取多个脚本号的sheet…Excel 1、只读取sheet0(只读取一个脚本号的Excel) 前言&#xff1a;引入pom文件 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</…

OV SSL证书申请指南

OV SSL证书除了验证域名所有权外还需要验证组织信息&#xff0c;这类证书适用于对公司官网、品牌、安全性等有较高程度要求的企业级用户。具体申请流程如下&#xff1a; 一 、注册账号 注册账号填写230919注册码即可获得大额优惠券和全程一对一技术支持https://www.joyssl.co…

网页速度如何优化?从10s到0.5s

如何排除网页速度慢的故障&#xff1f; 优化运行缓慢的网页涉及多个层面的改进&#xff0c;可分为硬件、前端和后台优化。下面是一份全面的指南&#xff1a; 01 硬件优化 服务器资源 升级服务器&#xff1a;确保服务器能为流量提供足够的资源&#xff08;CPU、内存、带宽等&a…

【Windows】Mountain Duck(FTP服务器管理工具)软件介绍

软件介绍 Mountain Duck是一款基于Cyberduck开发的应用程序&#xff0c;它允许用户通过FTP、SFTP、WebDAV、S3和OpenStack Swift等协议连接到云存储和远程服务器&#xff0c;并在本地文件浏览器中以熟悉的方式访问和管理这些文件。 功能特点 支持多种协议: Mountain Duck支持…

右键没有压缩选项

想压缩文件选中右键没有压缩选项。 打开任意rar文件 选择选项-》设置&#xff0c;添加到winrar到开始菜单即可

HTML+CSS+JavaScript实现烟花绽放的效果源码

源码 复制粘贴代码 在同级别下放一张图片fire.png接可以了 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

AI多模态模型架构之输出映射器:Output Projector

〔探索AI的无限可能&#xff0c;微信关注“AIGCmagic”公众号&#xff0c;让AIGC科技点亮生活〕 本文作者&#xff1a;AIGCmagic社区 刘一手 前言 AI多模态大模型发展至今&#xff0c;每年都有非常优秀的工作产出&#xff0c;按照当前模型设计思路&#xff0c;多模态大模型的…

QChart笔记6:显示点的值、显示点坐标值

在QChart笔记2: 添加鼠标悬停显示和格式处理_qchart 折线图 响应鼠标显示数据-CSDN博客上修改而来。 在笔记2中&#xff0c;通过鼠标悬停的方式显示了坐标轴Y的值&#xff0c;如果要一直显示应该怎么写呢&#xff1f;比如要达到下面的效果。 核心是这句&#xff1a; series1-…

Windows10安装——制作U盘启动盘(保姆级)

安装前准备&#xff1a; 一个不少于8G的U盘&#xff0c; 一个可以上网的windows电脑&#xff1b; 第一步&#xff1a;安装启动盘制作工具 首先我们下载启动盘制作工具&#xff0c; 官网网址&#xff1a;下载 Windows 10 (microsoft.com)&#xff1b; 百度网盘下载&#xf…

赛氪网受邀参加中国国际科技促进会第五届第五次常务理事扩大会议

2024年7月27日&#xff0c;环球赛乐&#xff08;北京&#xff09;科技有限公司&#xff08;以下简称“赛氪网”&#xff09;受邀参加了中国国际科技促进会第五届第五次常务理事扩大会议。此次会议汇聚了众多科技界的精英和专家&#xff0c;共同探讨科技发展的新方向&#xff0c…

【Mybatis】xml 配置文件

Mybatis的开发有两种方式&#xff1a; 注解XML 使用Mybatis的注解方式&#xff0c;主要是来完成一些简单的增删改查功能。 如果需要实现复杂的SQL功能&#xff0c;建议使用XML来配置映射语句&#xff0c;也就是将SQL语句写在XML配置文件中。在Mybatis中使用XML映射文件方式开…

Cxx primer-chap10-Generic Algorithms

generic algorithms的解释&#xff1a;&#xff0c;具体而言iterator使得算法与容器类型无关&#xff1a;&#xff0c;但算法的实现成功与否有时依赖于&#xff08;element type&#xff09;元素类型&#xff1a;通用算法的实现依赖于iterator&#xff0c;具体而言algorithm –…

python windows环境部署

在官网安装www.python.org linux系统的只能编译安装 windows的可以直接安装 这里是windows安装 .3.9.6版本 一直下一步就可以&#xff0c;然后鼠标右键在按住shift用终端打开 输入py或者python验证一下是否安装成功 打开目录文件夹 在里面新建一下pip的文件夹&#xff0c;里…