函数式编程

2024-05-29  
2条评论   132浏览

函数式编程:Lambda表达式+Stream流式调用+Chain链式调用+Java8函数式接口

Lambda表达式

(parameters) -> expression  
或  
(parameters) -> { statements; }

parameters:这是Lambda表达式的参数列表。类型可以从上下文推断出来,所以通常可以省略。

->:这是Lambda操作符,它分隔了参数列表和Lambda体。

expression 或 { statements; }:这是Lambda体,可以是一个表达式(返回该表达式的值)或是一个语句块(包含多条语句)。

Stream流式调用

import java.util.Arrays;  
import java.util.List;  
import java.util.function.Function;  
import java.util.stream.Collectors;  
  
public class FunctionalProgrammingExample {  
  
    public static void main(String[] args) {  
        // 创建一个整数列表  
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
  
        // 使用Stream API和Lambda表达式来过滤偶数并计算它们的平方和  
        int sumOfSquaresOfEvens = numbers.stream()  
                .filter(n -> n % 2 == 0) // 过滤偶数  
                .map(n -> n * n) // 计算平方  
                .mapToInt(Integer::intValue) // 转换为int流以便求和  
                .sum(); // 计算总和  
  
        // 输出结果  
        System.out.println("Sum of squares of even numbers: " + sumOfSquaresOfEvens);  
  
        // 使用Function接口和链式调用来转换列表中的每个元素  
        List<String> strings = numbers.stream()  
                .map(String::valueOf) // 将每个整数转换为字符串  
                .collect(Collectors.toList()); // 收集到新的列表中  
  
        // 输出结果  
        System.out.println("List of string representations: " + strings);  
  
        // 使用Consumer接口来处理列表中的每个元素  
        numbers.forEach(n -> System.out.print(n + " ")); // 打印每个元素  
        System.out.println(); // 换行  
  
        // 使用Supplier接口来生成一个值  
        Supplier<Integer> randomNumberGenerator = () -> (int) (Math.random() * 100);  
        int randomNumber = randomNumberGenerator.get(); // 获取随机生成的整数  
  
        // 输出结果  
        System.out.println("Random number: " + randomNumber);  
    }  
}

Chain链式调用

http://liyiru.site/blog/29

函数式接口:

  • Runnable:无参数、无返回值

  • Function:接受一个参数,并且有返回值

  • Consumer:接受一个参数,没有返回值

  • BiConsumer:接受两个参数,没有返回值

  • Supplier:没有参数,有返回值

案例

package com.bilibili.juc.cf;

import lombok.*;
import lombok.experimental.Accessors;

import java.awt.print.Book;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 *
 * 案例说明:电商比价需求,模拟如下情况:
 *
 * 1需求:
 *  1.1 同一款产品,同时搜索出同款产品在各大电商平台的售价;
 *  1.2 同一款产品,同时搜索出本产品在同一个电商平台下,各个入驻卖家售价是多少
 *
 * 2输出:出来结果希望是同款产品的在不同地方的价格清单列表,返回一个List<String>
 * 《mysql》 in jd price is 88.05
 * 《mysql》 in dangdang price is 86.11
 * 《mysql》 in taobao price is 90.43
 *
 * 3 技术要求
 *   3.1 函数式编程
 *   3.2 链式编程
 *   3.3 Stream流式计算
 */
public class CompletableFutureMallDemo
{
    static List<NetMall> list = Arrays.asList(
            new NetMall("jd"),
            new NetMall("dangdang"),
            new NetMall("taobao"),
            new NetMall("pdd"),
            new NetMall("tmall")
    );

    /**
     * step by step 一家家搜查
     * List<NetMall> ----->map------> List<String>
     * @param list
     * @param productName
     * @return
     */
    public static List<String> getPrice(List<NetMall> list,String productName)
    {
        //《mysql》 in taobao price is 90.43
        return list
                .stream()
                .map(netMall ->
                        String.format(productName + " in %s price is %.2f",
                                netMall.getNetMallName(),
                                netMall.calcPrice(productName)))
                .collect(Collectors.toList());
    }

    /**
     * List<NetMall> ----->List<CompletableFuture<String>>------> List<String>
     * @param list
     * @param productName
     * @return
     */
    public static List<String> getPriceByCompletableFuture(List<NetMall> list,String productName)
    {
        return list.stream()
                .map(
                    netMall ->
                    CompletableFuture.supplyAsync(() -> String.format(productName + " in %s price is %.2f",
                    netMall.getNetMallName(),
                    netMall.calcPrice(productName)))
                )
                .collect(
                    Collectors.toList()
                )
                .stream()
                .map(
                    s -> s.join()
                )
                .collect(
                    Collectors.toList()
                );
    }


    public static void main(String[] args)
    {
        long startTime = System.currentTimeMillis();

        List<String> list1 = getPrice(list, "mysql");
        for (String element : list1) {
            System.out.println(element);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("----costTime: "+(endTime - startTime) +" 毫秒");

        System.out.println("--------------------");

        long startTime2 = System.currentTimeMillis();
        List<String> list2 = getPriceByCompletableFuture(list, "mysql");
        for (String element : list2) {
            System.out.println(element);
        }
        long endTime2 = System.currentTimeMillis();
        System.out.println("----costTime: "+(endTime2 - startTime2) +" 毫秒");
    }
}

class NetMall
{
    @Getter
    private String netMallName;

    public NetMall(String netMallName)
    {
        this.netMallName = netMallName;
    }

    public double calcPrice(String productName)
    {
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}