流量型网站,工业产品外观设计,百度首页纯净版,台州免费建站一、介绍和入门
1、函数式编程介绍
函数式编程思想在于简化冗余代码#xff0c;将函数式接口#xff08;接口中只有一个未实现的方法#xff09;作为最高抽象。它关注的是入参、返回、语法结构#xff0c;是一种极简的编程方式。相对面向过程和面向对象编程#xff0c;函…一、介绍和入门
1、函数式编程介绍
函数式编程思想在于简化冗余代码将函数式接口接口中只有一个未实现的方法作为最高抽象。它关注的是入参、返回、语法结构是一种极简的编程方式。相对面向过程和面向对象编程函数编程是面向数据处理和计算过程的抽象与组合。 //在java中可以使用FunctionalInterface标识函数式接口其作用是检验接口中是否只有一个未实现的方法如
FunctionalInterface
public interface FunctionT, R {R apply(T var1);
}2、java中的函数式编程接口
在java.util.function包中提供了大量规范的函数式接口以避免过多使用自定义函数式接口 主要分为5类 Consumer结尾接收入参没有返回Supplier结尾没有入参有返回Function结尾接收入参有返回Predicate结尾断言返回boolean类型参数Operator结尾入参和返回参数类型相同 Consumer 接受一个参数无返回值
BiConsumer 接受两个参数无返回值
DoubleConsumer 接受一个double类型的参数无返回值
IntConsumer 接受一个int类型的参数无返回值
LongConsumer 接受一个long类型的参数无返回值
ObjDoubleConsumer 接受一个自定义类型的参数和一个double类型的参数无返回值
ObjIntConsumer 接受一个自定义类型的参数和一个int类型的参数无返回值
ObjLongConsumer 接受一个自定义类型的参数和一个long类型的参数无返回值
Function 接受一个参数有返回值
BiFunction 接受两个参数有返回值
DoubleFunction 接受一个double类型的参数有返回值
IntFunction 接受一个int类型的参数有返回值
LongFunction 接受一个long类型的参数有返回值
IntToDoubleFunction 接受一个int类型的参数返回一个double类型的值
IntToLongFunction 接受一个int类型的参数返回一个long类型的值
LongToDoubleFunction 接受一个long类型的参数返回一个double类型的值
LongToIntFunction 接受一个long类型的参数返回一个int类型的值
DoubleToIntFunction 接受一个double类型的参数返回一个int类型的值
DoubleToLongFunction 接受一个double类型的参数返回一个long类型的值
ToDoubleBiFunction 接受两个参数返回一个double类型的值
ToDoubleFunction 接受一个参数返回一个double类型的值
ToIntBiFunction 接受两个参数返回一个int类型的值
ToIntFunction 接受一个参数返回一个int类型的值
ToLongBiFunction 接受两个参数返回一个long类型的值
ToLongFunction 接受一个参数返回一个long类型的值
BinaryOperator 接受两个相同类型的参数返回一个相同类型的值
DoubleBinaryOperator 接受两个double类型的参数返回一个double类型的值
DoubleUnaryOperator 接受一个double类型的参数返回一个double类型的值
IntBinaryOperator 接受两个int类型的参数返回一个int类型的值
IntUnaryOperator 接受一个int类型的参数返回一个int类型的值
LongBinaryOperator 接受两个long类型的参数返回一个long类型的值
LongUnaryOperator 接受一个long类型的参数返回一个long类型的值
UnaryOperator 接受一个参数返回一个相同类型的值
Predicate 接受一个参数返回一个boolean类型的值
BiPredicate 接受两个参数返回一个boolean类型的值
DoublePredicate 接受一个double类型的参数返回一个boolean类型的值
IntPredicate 接受一个int类型的参数返回一个boolean类型的值
LongPredicate 接受一个long类型的参数返回一个boolean类型的值
Supplier 无参数有返回值
BooleanSupplier 无参数返回一个boolean类型的值
DoubleSupplier 无参数返回一个double类型的值
IntSupplier 无参数返回一个int类型的值
LongSupplier 无参数返回一个long类型的值 3、函数式编程配合Lambda表达式的简单实践 public static void main(String[] args) {//匿名内部类FunctionInteger, String function1 new FunctionInteger, String() {Overridepublic String apply(Integer i) {return String.valueOf(i);}};System.out.println(function1.apply(1));//简化FunctionInteger, String function2 i - String.valueOf(i);System.out.println(function2.apply(1));//再简化FunctionInteger, String function3 String::valueOf;System.out.println(function3.apply(1));//多个参数BiFunctionInteger, Integer, Integer biFunction (i, j) - i j;System.out.println(biFunction.apply(0, 1));//断言PredicateInteger predicate i - i 1;//判断是否满足条件System.out.println(predicate.test(2));//判断是否不满足条件System.out.println(predicate.negate().test(2));} 4、函数式编程特点 不可变性在函数式编程中数据是不可变的。这意味着一旦一个值被定义它就不能被改变。这种不可变性有助于减少程序中的错误和副作用因为你不必担心在某个地方意外地修改了数据。无副作用函数式编程中的函数通常没有副作用即它们不会修改全局状态或产生其他外部影响。这使得函数更加可预测和可测试因为你可以确信给定相同的输入函数将始终产生相同的输出。函数的纯粹性在函数式编程中函数是纯粹的即它们的结果只取决于其输入参数而不受外部状态的影响。这有助于简化代码和推理过程因为你不必考虑函数之外的任何状态或变量。高阶函数和闭包函数式编程鼓励使用高阶函数接受其他函数作为参数或返回函数的函数和闭包捕获其外部环境的函数。这些特性使得函数更加灵活和可组合可以方便地构建复杂的计算过程和数据结构。抽象和组合函数式编程强调通过抽象和组合来构建复杂的程序。你可以将计算过程分解为一系列简单的函数然后将它们组合在一起以实现更复杂的功能。这种方式有助于提高代码的可读性、可维护性和可重用性 5、函数式编程缺点 学习成本较高函数式编程的思维方式与传统的命令式编程有很大的不同。它强调不可变性、无副作用和函数的纯粹性这可能需要开发者花费更多的时间和精力来学习和适应。此外函数式编程通常使用高阶函数和闭包等高级特性这也增加了学习的难度。性能问题虽然函数式编程可以提高代码的可读性和可维护性但在某些情况下它可能不如命令式编程性能好。这主要是因为函数式编程强调不可变性和无副作用这可能导致大量的数据复制和函数调用从而增加了内存消耗和运行时间。然而现代的函数式编程语言和编译器已经采用了许多优化技术来缓解这个问题。调试困难由于函数式编程强调函数的纯粹性和无副作用这使得在调试过程中很难跟踪和定位错误。在命令式编程中你可以通过设置断点、打印日志等方式来跟踪程序的执行过程。但在函数式编程中由于函数之间没有共享的状态因此很难确定错误发生的位置和原因。与现有系统的兼容性函数式编程与传统的命令式编程在思维方式和编程风格上有很大的不同。这可能导致在将函数式编程与现有的命令式系统进行集成时出现兼容性问题。例如函数式编程强调不可变性和无副作用这可能与现有系统中的某些特性和库不兼容。可能的代码可读性问题虽然函数式编程可以提高代码的简洁性和可维护性但过度使用某些函数式编程特性如无参风格、大量方法的组合可能会影响代码的可读性。这使得其他开发者在阅读和理解代码时可能会遇到困难。 二、进阶
1、Java8 Stream Api流操作
代码示例 public static void main(String[] args) { // 创建一个整数列表 ListInteger numbers Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 使用Stream API进行过滤、映射和聚合操作 ListInteger result numbers.stream() // 创建流 .filter(n - n % 2 0) // 过滤偶数 .map(n - n * n) // 映射将每个数平方 .collect(Collectors.toList()); // 聚合将结果收集到一个新的列表中 // 输出结果[4, 16, 36, 64, 100]System.out.println(result); } Stream Api特点 流水线操作Stream API 的操作可以像流水线一样串联起来形成一个大的操作链。每个操作都可以看作是对数据源的一个转换或处理步骤。内部迭代Stream API 采用了内部迭代的方式具体的迭代过程则由流自行完成。这种方式简化了代码。 不可变性Stream API 中的流是不可变的。一旦一个流被创建就不能再修改它的数据源或操作。每次对流进行修改或转换都会返回一个新的流对象。这种不可变性保证了数据的安全性避免了在并发环境下的数据竞争问题。惰性求值Stream API 采用了惰性求值的方式。这意味着在中间处理过程中流只是对操作进行了记录并不会立即执行。只有当执行到终止操作时才会进行实际的计算。这种方式可以提高性能避免不必要的计算。丰富的操作Stream Api简化了Java开发中数据运算、聚合、分组、转换、比较、过滤、遍历、排序等操作通过使用Lambda表达式和函数式编程可以简化冗余复杂的代码这些操作可以方便地满足各种数据处理需求。 Stream Api使用注意点 流的操作默认多线程并行执行对于少量数据操作其性能可能不如传统写法此外在并发编程中流处理的中间操作过程中不应该介入有状态数据或将流中间操作的结果输出。流操作并不是每次对一个中间过程进行处理而是每次走完整个处理链。 Stream Api的中间操作和终端操作 中间操作 中间操作会返回一个新的流并允许链式操作。这些操作不会立即执行而是惰性求值的即只有当终端操作被触发时中间操作才会被应用到数据源上。常见的中间操作有 filter(Predicate? super T predicate) 过滤流中的元素只保留满足给定谓词的元素。map(Function? super T, ? extends R mapper) 将流中的每个元素映射成一个新的元素通常用于转换数据类型或提取信息。flatMap(Function? super T, ? extends Stream? extends R mapper) 将流中的每个元素映射成一个新的流然后将这些流合并成一个流。这通常用于将多个流合并成一个或将嵌套的数据结构展平。limit(long maxSize) 截断流使其只包含前 maxSize 个元素。这是一种短路操作即一旦达到指定的大小就会停止处理更多的元素。skip(long n) 跳过流中的前 n 个元素。如果流中的元素不足 n 个则返回一个空流。distinct() 返回一个包含所有不同元素的新流。这是通过流的元素的 equals() 方法进行比较的。sorted() 或 sorted(Comparator? super T comparator) 返回一个新流其中的元素按自然顺序排序或者根据提供的 Comparator 进行排序。peek(Consumer? super T action) 对流中的每个元素执行给定的操作并返回一个新的流包含原始元素。这主要用于调试目的因为它允许你查看流中的元素而不改变它们。mapToInt(ToIntFunction? super T mapper), mapToLong(ToLongFunction? super T mapper), mapToDouble(ToDoubleFunction? super T mapper) 这些操作将流中的元素映射成基本数据类型int, long, double的流如 IntStream, LongStream, DoubleStream。这对于需要进行数值计算的情况非常有用。 终端操作 终端操作会触发实际的计算并关闭流。流只能被遍历一次因此终端操作之后流就不能再被使用了。常见的终端操作有 forEach(Consumer? super T action) 对流中的每个元素执行给定的操作。这通常用于遍历流并执行某种副作用。collect(Collector? super T, A, R collector) 使用提供的Collector对流中的元素进行归约操作并将结果收集到一个目标对象中通常是集合或其他数据结构。toArray() 将流中的元素收集到一个数组中。这个方法有两种形式无参的toArray()它返回一个Object[]以及toArray(IntFunctionA[] generator)它允许你指定数组的类型和大小。reduce(T identity, BinaryOperatorT accumulator) 使用给定的累积函数对流中的元素进行归约操作并返回归约的结果。identity是归约的初始值。min(Comparator? super T comparator) 和 max(Comparator? super T comparator) 根据提供的比较器返回流中的最小或最大元素。返回的是一个OptionalT表示最小或最大元素可能存在也可能不存在。count() 返回流中的元素数量。这是一个长整型值可以处理比Integer.MAX_VALUE更大的流。anyMatch(Predicate? super T predicate) 判断流中是否有任何元素匹配给定的谓词。如果有一个元素满足条件就返回true。allMatch(Predicate? super T predicate) 判断流中的所有元素是否都匹配给定的谓词。只有当所有元素都满足条件时才返回true。noneMatch(Predicate? super T predicate) 判断流中是否没有任何元素匹配给定的谓词。如果所有元素都不满足条件就返回true。findFirst() 返回流中的第一个元素。返回的是一个OptionalT表示第一个元素可能存在也可能不存在。findAny() 返回流中的任意一个元素。在并行流中这个方法可能会更高效因为它允许从任何部分获取元素。返回的也是一个OptionalT。 这两种操作类型一起构成了 Stream API 强大的数据处理和分析能力。中间操作允许我们构建复杂的查询和转换管道而终端操作则负责触发实际的计算和结果提取。 本文引用
函数式编程有哪些好处_函数式编程语言有哪些_Js函数式编程好处 - 腾讯云开发者社区 - 腾讯云
Stream流API总结_stream流常用api-CSDN博客 java Stream类的 超全API及实战总结_java stream api-CSDN博客
在Stream流中添加中间操作_stream添加元素-CSDN博客
在Stream上添加终端操作_tounmodifiableset-CSDN博客