当前位置: 首页 > news >正文

Java 进阶--函数式编程

文章目录

    • 前言
    • 函数式编程
    • Java函数式编程的核心概念
      • 函数式接口(Functional Interface)
      • Lambda表达式
    • Java内置的函数式接口
      • 常用函数式接口
    • 方法引用(Method Reference)
    • Stream API - 函数式编程的核心工具
      • Stream基本操作
      • 高级Stream操作
    • Optional类 - 避免空指针异常
    • 函数组合和高阶函数
    • 实际应用案例
      • 数据处理管道
      • 异步编程
      • 常见陷阱
    • 总结
    • 完整代码

前言

当你迷茫的时候,请点击 目录大纲 快速查看前面的技术文章,相信你总能找到前行的方向

另外,本文相关代码已上传 gitee仓库,欢迎关注收藏

函数式编程

函数式编程(Functional Programming,FP)是一种编程范式,它将计算视为数学函数的求值,并避免使用可变状态和可变数据。在Java中,函数式编程主要通过Lambda表达式方法引用来实现。

Java函数式编程的核心概念

函数式接口(Functional Interface)

定义一个抽象方法的接口,方法的就能以这个接口形式进行传参。

// 只有一个抽象方法的接口
@FunctionalInterface
public interface MyFunction {int apply(int a, int b);// 可以有默认方法default void printResult(int result) {System.out.println("结果: " + result);}// 可以有静态方法static MyFunction add() {return (a, b) -> a + b;}
}

这样,函数可以当成一个普通参数进行传递,例如 MyFunction.add() 直接传参,在 func.apply(a, b) 使用方法参数调用加法。

    public static void main(String[] args) {// 函数式接口doSomething(MyFunction.add(),2,3);}private static void doSomething(MyFunction func,int a,int b){int res = func.apply(a, b); 	// 调用add()方法求 a+bfunc.printResult(res); 			// MyFunction printResult 结果: 5}

Lambda表达式

// 基本语法: (parameters) -> expression
// 或: (parameters) -> { statements; }
// 示例public static void main(String[] args) {Runnable runnable = () -> System.out.println("-1- runnable: Hello");Thread t = new Thread(runnable);t.start();Comparator<Integer> comparator = (a, b) -> a - b;System.out.println("-2- comparator 排序:"+ Stream.of(9,5,6,3,4,2,1,8,7).sorted(comparator).collect(Collectors.toList()));MyFunction add = (a, b) -> a + b;MyFunction multiply = (a, b) -> a * b;System.out.println("-3- add.apply(2,3): " + add.apply(2, 3));System.out.println("-4- multiply.apply(2,3): " + multiply.apply(2, 3));}

结果如下:

-1- runnable: Hello
-2- comparator 排序:[1, 2, 3, 4, 5, 6, 7, 8, 9]
-3- add.apply(2,3): 5
-4- multiply.apply(2,3): 6

Java内置的函数式接口

常用函数式接口

private static void testCommFunction() {// Predicate<T> - 接受一个参数,返回booleanPredicate<String> isLong = s -> s.length() > 5;System.out.println(isLong.test("Hello")); // false// Function<T, R> - 接受一个参数,返回结果Function<String, Integer> stringLength = String::length;System.out.println(stringLength.apply("Hello")); // 5// Consumer<T> - 接受一个参数,无返回值Consumer<String> printer = System.out::println;printer.accept("Hello World");// Supplier<T> - 无参数,返回一个结果Supplier<Double> randomSupplier = Math::random;System.out.println(randomSupplier.get());// UnaryOperator<T> - 接受一个参数,返回同类型结果UnaryOperator<String> toUpper = String::toUpperCase;System.out.println(toUpper.apply("hello")); // HELLO// BinaryOperator<T> - 接受两个同类型参数,返回同类型结果BinaryOperator<Integer> sum = Integer::sum;System.out.println(sum.apply(5, 3)); // 8}

方法引用(Method Reference)

    private static void testMethodRefFunction() {List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "\n");// 1. 静态方法引用names.forEach(System.out::println);// 2. 实例方法引用String prefix = "Hello, ";names.stream().map(prefix::concat).forEach(System.out::println);// 3. 特定类型的任意对象方法引用names.sort(String::compareToIgnoreCase);// 4. 构造方法引用names.stream().map(String::new).forEach(System.out::println);// 自定义方法用于方法引用System.out.println("\n过滤偶数:" + Stream.of(9, 5, 6, 3, 4, 2, 1, 8, 7).filter(Main::isEven).collect(Collectors.toList()));}public static boolean isEven(int number) {return number % 2 == 0;}

结果如下:

Charlie
Alice
BobHello, Charlie
Hello, Alice
Hello, Bob
Hello, Alice
Bob
Charlie过滤偶数:[6, 4, 2, 8]

Stream API - 函数式编程的核心工具

Stream基本操作

    public static void testStream() {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 过滤和映射List<Integer> result = numbers.stream().filter(n -> n % 2 == 0)        // 中间操作:过滤偶数.map(n -> n * n)               // 中间操作:平方.collect(Collectors.toList()); // 终端操作:收集结果System.out.println(result); // [4, 16, 36, 64, 100]// 更多操作numbers.stream().distinct()                    // 去重.sorted()                      // 排序.limit(5)                      // 限制数量.skip(2)                       // 跳过前n个.forEach(System.out::println); // 遍历}

高级Stream操作

    public static void testStream2() {List<String> words = Arrays.asList("Hello", "World", "Java", "Stream");// 归约操作Optional<Integer> totalLength = words.stream().map(String::length).reduce(Integer::sum);System.out.println("总长度: " + totalLength.orElse(0));// 分组Map<Integer, List<String>> lengthMap = words.stream().collect(Collectors.groupingBy(String::length));System.out.println("按长度分组: " + lengthMap);// 分区Map<Boolean, List<String>> partition = words.stream().collect(Collectors.partitioningBy(s -> s.length() > 4));System.out.println("按长度分区: " + partition);// 连接字符串String joined = words.stream().collect(Collectors.joining(", ", "[", "]"));System.out.println("连接结果: " + joined);}

结果如下:

总长度: 20
按长度分组: {4=[Java], 5=[Hello, World], 6=[Stream]}
按长度分区: {false=[Java], true=[Hello, World, Stream]}
连接结果: [Hello, World, Java, Stream]

Optional类 - 避免空指针异常

    public static void testOptional() {// 创建OptionalOptional<String> empty = Optional.empty();Optional<String> nonEmpty = Optional.of("Hello");Optional<String> nullable = Optional.ofNullable(null);// 使用OptionalString result = nullable.map(String::toUpperCase)          // 如果值存在则转换.orElse("Default Value");         // 如果为空返回默认值System.out.println(result); // Default Valuenullable.ifPresent(value -> System.out.println("值存在: " + value));// 链式操作Optional<String> finalResult = Optional.of(nonEmpty.filter(s -> s.length() > 3).map(String::toUpperCase).orElse("FALLBACK"));System.out.println(finalResult.get()); // HELLO}

函数组合和高阶函数

 public static void testComposeFunction() {// 函数组合Function<Integer, Integer> multiplyBy2 = x -> x * 2;Function<Integer, Integer> add3 = x -> x + 3;// andThen: 先执行当前函数,再执行参数函数Function<Integer, Integer> multiplyAndAdd = multiplyBy2.andThen(add3);System.out.println(multiplyAndAdd.apply(5)); // 13// compose: 先执行参数函数,再执行当前函数Function<Integer, Integer> addAndMultiply = multiplyBy2.compose(add3);System.out.println(addAndMultiply.apply(5)); // 16// Predicate组合Predicate<Integer> isEven = x -> x % 2 == 0;Predicate<Integer> isGreaterThan10 = x -> x > 10;Predicate<Integer> isEvenAndGreaterThan10 = isEven.and(isGreaterThan10);System.out.println(isEvenAndGreaterThan10.test(12)); // trueSystem.out.println(isEvenAndGreaterThan10.test(8));  // false// Consumer组合Consumer<String> print = System.out::println;Consumer<String> printTwice = print.andThen(print);printTwice.accept("Hello");}

实际应用案例

数据处理管道

定义 Person 类

public class Person {private String name;private int age;private double salary;public Person(String name, int age, double salary) {this.name = name;this.age = age;this.salary = salary;}// getterspublic String getName() { return name; }public int getAge() { return age; }public double getSalary() { return salary; }
}

测试程序

    public static void testPipeline() {List<Person> people = Arrays.asList(new Person("Alice", 25, 50000),new Person("Bob", 30, 60000),new Person("Charlie", 35, 70000),new Person("Diana", 28, 55000));// 复杂的数据处理管道Map<String, Double> result = people.stream()// 过滤年龄.filter(p -> p.getAge() > 25)// 按薪资排序.sorted(Comparator.comparing(Person::getSalary))// 分组求平均薪资.collect(Collectors.groupingBy(p -> p.getAge() > 30 ? "Senior" : "Junior",Collectors.averagingDouble(Person::getSalary)));System.out.println(result);}

异步编程

import java.util.concurrent.*;
import java.util.function.*;public class AsyncProgramming {public static void main(String[] args) throws Exception {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);return "Hello";} catch (InterruptedException e) {throw new IllegalStateException(e);}});CompletableFuture<String> result = future.thenApply(String::toUpperCase).thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World")).exceptionally(ex -> "Error: " + ex.getMessage());System.out.println(result.get()); // HELLO World}
}

常见陷阱

    // 在Lambda中修改外部变量public static void modifyingExternalVariable() {int[] counter = {0};List<String> items = Arrays.asList("A", "B", "C");// 不好的做法:修改外部变量items.forEach(item -> counter[0]++);System.out.println(counter[0]);// 好的做法:使用归约long count = items.stream().count();System.out.println(count);}//过度使用链式操作public static void avoidOverChaining() {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 不好的:过度链式操作,难以调试int result = numbers.stream().filter(n -> n > 2).map(n -> n * 2).sorted().distinct().reduce(0, Integer::sum);System.out.println(result);// 好的:分步骤,清晰可读List<Integer> filtered = numbers.stream().filter(n -> n > 2).collect(Collectors.toList());List<Integer> doubled = filtered.stream().map(n -> n * 2).collect(Collectors.toList());int sum = doubled.stream().reduce(0, Integer::sum);System.out.println(sum);}

总结

Java函数式编程的核心要点:

  1. 函数式接口:只有一个抽象方法的接口
  2. Lambda表达式:简洁的函数表示法
  3. 方法引用:更简洁的Lambda写法
  4. Stream API:强大的数据处理工具
  5. Optional:优雅的空值处理
  6. 函数组合:构建复杂操作

函数式编程使代码更简洁、可读性更强,并且更容易进行并行处理。但需要注意合理使用,避免过度复杂化。

完整代码

函数式接口 MyFunction.java

package function;
@FunctionalInterface
public interface MyFunction {int apply(int a, int b);//可以有默认方法default void printResult(int result) {System.out.println("MyFunction printResult 结果: " + result);}//可以有静态方法static MyFunction add() {return (a, b) -> a + b;}
}

Person.java

package function;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
class Person {private String name;private int age;private double salary;
}

主测试类 Main.java

package function;import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** 函数式编程测试*/
public class Main {public static void main(String[] args) throws Exception {// 函数式接口doSomething(MyFunction.add(), 2, 3);// Lambda函数接口testLambdaFunction();// 常用函数式接口testCommFunction();// 方法引用testMethodRefFunction();// stream 基本操作testStream();// 高级Stream操作testStream2();// optionaltestOptional();// 函数组合testComposeFunction();// 数据处理管道testPipeline();// 异步编程testAsync();// 在Lambda中修改外部变量modifyingExternalVariable();//过度使用链式操作avoidOverChaining();}private static void testMethodRefFunction() {List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "\n");// 1. 静态方法引用names.forEach(System.out::println);// 2. 实例方法引用String prefix = "Hello, ";names.stream().map(prefix::concat).forEach(System.out::println);// 3. 特定类型的任意对象方法引用names.sort(String::compareToIgnoreCase);// 4. 构造方法引用names.stream().map(String::new).forEach(System.out::println);// 自定义方法用于方法引用System.out.println("\n过滤偶数:" + Stream.of(9, 5, 6, 3, 4, 2, 1, 8, 7).filter(Main::isEven).collect(Collectors.toList()));}public static boolean isEven(int number) {return number % 2 == 0;}private static void doSomething(MyFunction func, int a, int b) {int res = func.apply(a, b);func.printResult(res);}private static void testLambdaFunction() {Runnable runnable = () -> System.out.println("-1- runnable: Hello");Thread t = new Thread(runnable);t.start();Comparator<Integer> comparator = (a, b) -> a - b;System.out.println("-2- comparator 排序:" + Stream.of(9, 5, 6, 3, 4, 2, 1, 8, 7).sorted(comparator).collect(Collectors.toList()));MyFunction add = (a, b) -> a + b;MyFunction multiply = (a, b) -> a * b;System.out.println("-3- add.apply(2,3): " + add.apply(2, 3));System.out.println("-4- multiply.apply(2,3): " + multiply.apply(2, 3));}private static void testCommFunction() {// Predicate<T> - 接受一个参数,返回booleanPredicate<String> isLong = s -> s.length() > 5;System.out.println(isLong.test("Hello")); // false// Function<T, R> - 接受一个参数,返回结果Function<String, Integer> stringLength = String::length;System.out.println(stringLength.apply("Hello")); // 5// Consumer<T> - 接受一个参数,无返回值Consumer<String> printer = System.out::println;printer.accept("Hello World");// Supplier<T> - 无参数,返回一个结果Supplier<Double> randomSupplier = Math::random;System.out.println(randomSupplier.get());// UnaryOperator<T> - 接受一个参数,返回同类型结果UnaryOperator<String> toUpper = String::toUpperCase;System.out.println(toUpper.apply("hello")); // HELLO// BinaryOperator<T> - 接受两个同类型参数,返回同类型结果BinaryOperator<Integer> sum = Integer::sum;System.out.println(sum.apply(5, 3)); // 8}public static void testStream() {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 过滤和映射List<Integer> result = numbers.stream().filter(n -> n % 2 == 0)        // 中间操作:过滤偶数.map(n -> n * n)               // 中间操作:平方.collect(Collectors.toList()); // 终端操作:收集结果System.out.println(result); // [4, 16, 36, 64, 100]// 更多操作numbers.stream().distinct()                    // 去重.sorted()                      // 排序.limit(5)                      // 限制数量.skip(2)                       // 跳过前n个.forEach(System.out::println); // 遍历}public static void testStream2() {List<String> words = Arrays.asList("Hello", "World", "Java", "Stream");// 归约操作Optional<Integer> totalLength = words.stream().map(String::length).reduce(Integer::sum);System.out.println("总长度: " + totalLength.orElse(0));// 分组Map<Integer, List<String>> lengthMap = words.stream().collect(Collectors.groupingBy(String::length));System.out.println("按长度分组: " + lengthMap);// 分区Map<Boolean, List<String>> partition = words.stream().collect(Collectors.partitioningBy(s -> s.length() > 4));System.out.println("按长度分区: " + partition);// 连接字符串String joined = words.stream().collect(Collectors.joining(", ", "[", "]"));System.out.println("连接结果: " + joined);}public static void testOptional() {// 创建OptionalOptional<String> empty = Optional.empty();Optional<String> nonEmpty = Optional.of("Hello");Optional<String> nullable = Optional.ofNullable(null);// 使用OptionalString result = nullable.map(String::toUpperCase)          // 如果值存在则转换.orElse("Default Value");         // 如果为空返回默认值System.out.println(result); // Default Valuenullable.ifPresent(value -> System.out.println("值存在: " + value));// 链式操作Optional<String> finalResult = Optional.of(nonEmpty.filter(s -> s.length() > 3).map(String::toUpperCase).orElse("FALLBACK"));System.out.println(finalResult.get()); // HELLO}public static void testComposeFunction() {// 函数组合Function<Integer, Integer> multiplyBy2 = x -> x * 2;Function<Integer, Integer> add3 = x -> x + 3;// andThen: 先执行当前函数,再执行参数函数Function<Integer, Integer> multiplyAndAdd = multiplyBy2.andThen(add3);System.out.println(multiplyAndAdd.apply(5)); // 13// compose: 先执行参数函数,再执行当前函数Function<Integer, Integer> addAndMultiply = multiplyBy2.compose(add3);System.out.println(addAndMultiply.apply(5)); // 16// Predicate组合Predicate<Integer> isEven = x -> x % 2 == 0;Predicate<Integer> isGreaterThan10 = x -> x > 10;Predicate<Integer> isEvenAndGreaterThan10 = isEven.and(isGreaterThan10);System.out.println(isEvenAndGreaterThan10.test(12)); // trueSystem.out.println(isEvenAndGreaterThan10.test(8));  // false// Consumer组合Consumer<String> print = System.out::println;Consumer<String> printTwice = print.andThen(print);printTwice.accept("Hello");}public static void testPipeline() {List<Person> people = Arrays.asList(new Person("Alice", 25, 50000),new Person("Bob", 30, 60000),new Person("Charlie", 35, 70000),new Person("Diana", 28, 55000));// 复杂的数据处理管道Map<String, Double> result = people.stream()// 过滤年龄.filter(p -> p.getAge() > 25)// 按薪资排序.sorted(Comparator.comparing(Person::getSalary))// 分组求平均薪资.collect(Collectors.groupingBy(p -> p.getAge() > 30 ? "Senior" : "Junior",Collectors.averagingDouble(Person::getSalary)));System.out.println(result);}public static void testAsync() throws Exception {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);return "Hello";} catch (InterruptedException e) {throw new IllegalStateException(e);}});CompletableFuture<String> result = future.thenApply(String::toUpperCase).thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World")).exceptionally(ex -> "Error: " + ex.getMessage());// HELLO WorldSystem.out.println(result.get());}public static void modifyingExternalVariable() {int[] counter = {0};List<String> items = Arrays.asList("A", "B", "C");// 不好的做法:修改外部变量items.forEach(item -> counter[0]++);System.out.println(counter[0]);// 好的做法:使用归约long count = items.stream().count();System.out.println(count);}public static void avoidOverChaining() {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 不好的:过度链式操作,难以调试int result = numbers.stream().filter(n -> n > 2).map(n -> n * 2).sorted().distinct().reduce(0, Integer::sum);System.out.println(result);// 好的:分步骤,清晰可读List<Integer> filtered = numbers.stream().filter(n -> n > 2).collect(Collectors.toList());List<Integer> doubled = filtered.stream().map(n -> n * 2).collect(Collectors.toList());int sum = doubled.stream().reduce(0, Integer::sum);System.out.println(sum);}}
http://www.dtcms.com/a/428010.html

相关文章:

  • 《道德经》第九章
  • 网站首页怎么做ps中国营销传播网
  • 镇江网友之家百度上如何做优化网站
  • 网站分辨率自适应代码模板网站定制网站
  • 建设网站的网站安全建设银行网站怎么修改手机号码吗
  • 网站后台可以做两个管理系统么wordpress wpenqueuestyle
  • 两种常见的ACM风格笔试题
  • 图神经网络分享系列-transe(Translating Embeddings for Modeling Multi-relational Data) (一)
  • ENVI系列教程(十九)——目标探测与识别
  • 校园超市网站开发整站优seo排名点击
  • 服务器放n个网站自己做鞋子网站
  • Spring核心 - 控制反转 IOC , 用来大量例子来解释
  • 关键词查询的分析网站有网打不开网页咋回事
  • 大型电子商务网站建设成本双流区的规划建设局网站
  • 从引流到生态:排队免单如何重构商家私域流量?
  • 云网站制作的流程图烟台网站制作厂家联系方式
  • 做视频网站要多大的主机中国建设人才信息网查
  • 网站建设发文章几点发比较合适网站开发 平均工资
  • Android dm设备和分区关系以及文件系统介绍
  • 安卓基础组件013--button
  • @MySQL 主从自动修复 - 复制错误
  • 一级造价工程师报名网站枝江市住房和城乡建设局网站
  • 网站上传程序流程it外包公司是什么意思
  • Day1 Linux 入门:9 个核心命令(whoami/id/pwd 等)
  • 【RabbitMQ】docker-compose编排部署RabbitMQ容器——CentOS
  • 免费推广网站2024建设一个图片下载网站
  • TypeScript的类型兼容是什么?
  • 网站怎么提交收录建立网站需要多少钱?
  • PySpark全面解析:大数据处理的Python利器
  • 淮北哪些企业做网站商务网站建设论文总结