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

函数式接口:现代编程的利器

1. 引言

在软件开发的演进过程中,函数式编程(Functional Programming, FP)逐渐显露头角,成为解决复杂问题的有效工具之一。函数式接口作为函数式编程的核心概念之一,其重要性不言而喻。本文将深入探讨函数式接口的概念、应用以及它在现代编程中的重要作用。

2. 函数式接口的基础

函数式接口是函数式编程中一个至关重要的概念,它为编写简洁、可维护的代码提供了强大的支持。在本章节中,我们将深入探讨函数式接口的基本概念、特性以及它在Java语言中的实现。

2.1 定义与特性

函数式接口是指只包含一个抽象方法的接口。这种接口的设计理念是将行为抽象化,使得我们可以将方法作为参数传递给其他方法,或者将方法作为返回值返回。函数式接口通常用于实现高阶函数,即函数的参数或返回值也是函数。

2.2 与普通接口的区别

普通接口可以包含多个方法,而函数式接口则限制为只有一个抽象方法。这种限制使得函数式接口非常适合作为Lambda表达式的目标类型。Lambda表达式可以被视为匿名的函数式接口实例,它允许我们以一种非常简洁的方式实现函数式接口。

2.3 Java中的实现

Java 8是Java语言中一个重要的里程碑,它引入了java.util.function包,这个包中定义了一系列的函数式接口,例如:

  • Supplier<T>:提供类型为T的对象实例。
  • Consumer<T>:接受类型为T的对象,并对其执行某些操作。
  • Function<T, R>:接受类型为T的对象,返回类型为R的对象。
  • Predicate<T>:接受类型为T的对象,并返回一个布尔值,用于表示断言。
  • UnaryOperator<T>:接受类型为T的对象,返回同一类型的结果。
  • BinaryOperator<T>:接受两个类型为T的对象,返回同一类型的结果。

这些接口为Java开发者提供了强大的工具,使得他们可以更加方便地实现函数式编程。

2.4 函数式接口的实现示例

让我们通过一个简单的例子来展示如何实现一个函数式接口:

@FunctionalInterface
public interface SimpleMathOperation {int operation(int a, int b);
}// 使用Lambda表达式实现SimpleMathOperation接口
SimpleMathOperation add = (a, b) -> a + b;
int result = add.operation(5, 3); // 结果为8

在上面的例子中,我们定义了一个简单的函数式接口SimpleMathOperation,它包含一个接受两个整数参数并返回一个整数结果的方法operation。然后,我们使用Lambda表达式(a, b) -> a + b来创建一个实现了该接口的实例,并调用它来执行加法操作。

3. 函数式接口的使用场景

函数式接口因其简洁、灵活的特性,在现代软件开发中扮演着越来越重要的角色。本章节将深入探讨函数式接口在不同编程场景中的应用,并提供丰富的代码示例,以展示它们如何帮助我们编写更加优雅和高效的代码。

3.1 并发编程中的应用

在并发编程中,函数式接口可以简化线程管理,并提高程序的可读性和可维护性。例如,Java 8中的CompletableFuture提供了supplyAsync方法,它接受一个Supplier函数式接口,用于异步执行任务:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时操作try {Thread.sleep(2000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return 42; // 任务结果
});future.thenAccept(System.out::println); // 处理结果

在这个示例中,我们使用supplyAsync来异步执行一个耗时操作,并在操作完成后处理结果。使用System.out::println作为方法引用,简化了Lambda表达式的书写。

3.2 事件驱动编程中的应用

在事件驱动编程中,函数式接口常用于定义事件处理器。例如,在使用JavaFX进行GUI编程时,可以利用EventHandler接口处理按钮点击事件:

Button button = new Button("Click me");
button.setOnAction(event -> {System.out.println("Button was clicked!");
});

这里,我们使用Lambda表达式创建了一个实现了EventHandler<ActionEvent>接口的匿名类,用于响应按钮点击事件。这种方式比传统的匿名内部类更加简洁。

3.3 数据流处理中的应用

在处理数据流时,函数式接口提供了一种声明式的方法来转换和聚合数据。以下是使用Java 8的Stream API对一组数字进行过滤和映射的示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long count = numbers.stream().filter(n -> n % 2 == 0) // 使用Predicate接口过滤偶数.map(n -> n * n)       // 使用Function接口进行平方操作.count();              // 计算结果的数量System.out.println("Count of squared even numbers: " + count);

在这个例子中,filtermap方法分别接受PredicateFunction接口的实现,用于对流中的元素进行过滤和转换。这种方式使得数据处理变得非常直观和易于理解。

3.4 策略模式的实现

函数式接口也可以用于实现策略模式,允许在运行时动态选择算法或行为。以下是使用函数式接口实现策略模式的示例:

@FunctionalInterface
interface CalculationStrategy {int calculate(int x, int y);
}// 实现加法策略
CalculationStrategy add = (x, y) -> x + y;
// 实现乘法策略
CalculationStrategy multiply = (x, y) -> x * y;public class Calculator {private CalculationStrategy strategy;public void setStrategy(CalculationStrategy strategy) {this.strategy = strategy;}public int executeStrategy(int x, int y) {return strategy.calculate(x, y);}
}// 使用Calculator
Calculator calculator = new Calculator();
calculator.setStrategy(add);
System.out.println(calculator.executeStrategy(5, 3)); // 输出 8calculator.setStrategy(multiply);
System.out.println(calculator.executeStrategy(5, 3)); // 输出 15

在这个示例中,CalculationStrategy是一个函数式接口,定义了一个calculate方法。我们为这个接口提供了两个实现:一个用于加法,一个用于乘法。Calculator类使用这个接口来动态改变其行为,从而实现了策略模式。

3.5 排序和搜索算法的实现

函数式接口也可以用于实现排序和搜索算法。例如,Java中的ArraysCollections类提供了sort方法的重载版本,它们接受Comparator函数式接口作为参数:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Collections.sort(names, String::compareTo); // 升序排序names.sort((a, b) -> b.compareTo(a)); // 降序排序

在这个例子中,我们首先使用String::compareTo作为方法引用对列表进行升序排序,然后通过Lambda表达式实现降序排序。

3.6 构建自定义函数式接口

除了Java内置的函数式接口,我们还可以根据自己的需求定义自定义的函数式接口。例如,假设我们需要一个接口来执行一些条件检查:

@FunctionalInterface
interface ConditionChecker<T> {boolean check(T t);
}List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream().filter(new ConditionChecker<Integer>() {@Overridepublic boolean check(Integer number) {return number % 2 == 0;}}).collect(Collectors.toList());System.out.println(evenNumbers); // 输出 [2, 4]

在这个示例中,我们定义了一个ConditionChecker接口,它接受一个类型为T的对象并返回一个布尔值。然后,我们创建了一个实现了ConditionChecker的匿名类实例,并在Stream API的filter方法中使用它来筛选出偶数。

4. Java中的函数式接口

Java 8通过java.util.function包引入了一系列函数式接口,它们极大地丰富了Java编程的表达能力,使得代码更加简洁和易于理解。这些接口在不同的编程场景中扮演着关键角色。以下是对这些接口的详细介绍及其使用场景的示例。

4.1 Supplier<T>接口

使用场景:当需要延迟初始化或按需创建对象时,Supplier<T>接口非常有用。

Supplier<Person> personSupplier = () -> new Person("John Doe", 30);
Person person = personSupplier.get(); // 按需创建Person对象

4.2 Consumer<T>接口

使用场景Consumer<T>接口适用于执行对单个元素的操作,如日志记录、用户界面更新等。

Consumer<String> logger = (message) -> System.out.println("Log: " + message);
logger.accept("This is an informational message."); // 日志记录

4.3 Function<T, R>接口

使用场景Function<T, R>接口用于对数据进行转换,常见于数据处理和转换操作。

Function<String, Integer> stringToLength = String::length;
Integer length = stringToLength.apply("Hello, World!"); // 字符串长度转换

4.4 Predicate<T>接口

使用场景Predicate<T>接口用于条件检查,如过滤集合中的元素。

Predicate<Integer> isEven = num -> num % 2 == 0;
boolean hasEvenNumber = Arrays.stream(new int[]{1, 2, 3, 4, 5}).anyMatch(isEven); // 检查是否有偶数

4.5 UnaryOperator<T>接口

使用场景:作为Function<T, T>的特化,UnaryOperator<T>接口适用于对同一类型的数据执行操作,如数值的转换。

UnaryOperator<Integer> increment = n -> n + 1;
int incrementedValue = increment.apply(5); // 数值加1操作

4.6 BinaryOperator<T>接口

使用场景BinaryOperator<T>接口用于对两个相同类型的数据执行二元操作,如求两个数的最大值。

BinaryOperator<Integer> max = (a, b) -> Math.max(a, b);
int maxValue = max.apply(10, 20); // 求两个数的最大值

4.7 BiFunction<T, U, R>接口

使用场景BiFunction<T, U, R>接口适用于需要两个输入参数的复杂映射操作,如基于两个参数计算结果。

BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
int result = sum.apply(5, 10); // 两个整数求和

4.8 BiPredicate<T, U>接口

使用场景BiPredicate<T, U>接口用于两个参数的条件判断,适用于复杂的过滤逻辑。

BiPredicate<Integer, Integer> isDivisible = (dividend, divisor) -> dividend % divisor == 0;
boolean isDivisibleResult = isDivisible.test(10, 5); // 检查是否能整除

4.9 Comparator<T>接口

使用场景Comparator<T>接口用于定义对象的比较规则,常用于排序操作。

Comparator<Person> byAge = Comparator.comparingInt(Person::getAge);
List<Person> sortedByAge = people.stream().sorted(byAge).collect(Collectors.toList()); // 按年龄排序

4.10 组合函数式接口

使用场景:组合函数式接口可以创建复杂的操作链,如数据处理流水线。

Function<String, Integer> toLength = String::length;
Function<Integer, Integer> increment = n -> n + 1;Function<String, Integer> processString = toLength.andThen(increment);
int processedResult = processString.apply("Kimi"); // 字符串长度加1

5. 高阶函数和Lambda表达式

高阶函数和Lambda表达式是函数式编程的核心概念,它们允许我们以声明式的方式处理数据和逻辑。在Java中,高阶函数是指可以接受另一个函数作为参数或者返回一个函数的函数。Lambda表达式提供了一种简洁的方式来实现函数式接口,使得代码更加简洁和易于理解。本章节将详细介绍高阶函数和Lambda表达式的概念、特性以及实际应用示例。

5.1 高阶函数的概念

使用场景:高阶函数在需要根据不同条件执行不同操作时非常有用,例如策略模式的实现。

@FunctionalInterface
interface Strategy<T> {T execute(Object input);
}// 定义一个高阶函数,它接受一个策略并返回执行结果
<T> T executeStrategy(Strategy<T> strategy, Object input) {return strategy.execute(input);
}// 实现一个具体的策略
Strategy<Double> addTax = (input) -> (Double) input * 1.05;double result = executeStrategy(addTax, 100.0); // 结果为105.0

5.2 Lambda表达式的概念

使用场景:Lambda表达式在需要匿名内部类时非常有用,特别是在实现函数式接口时。

// 使用Lambda表达式实现Runnable接口
Runnable r = () -> System.out.println("Hello, Lambda!");
r.run();

5.3 Lambda表达式与函数式接口的结合

使用场景:Lambda表达式与函数式接口结合使用,可以简化代码,特别是在使用Stream API时。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().filter(name -> name.length() > 4).sorted((a, b) -> b.compareTo(a)).forEach(name -> System.out.println(name));

5.4 方法引用

使用场景:方法引用是Lambda表达式的一种更简洁的形式,特别适用于引用已有方法。

// 使用方法引用作为Lambda表达式
Integer sum = Arrays.stream(new Integer[]{1, 2, 3, 4}).reduce(0, Integer::sum); // 使用Integer::sum作为方法引用

5.5 构造器引用

使用场景:构造器引用允许我们创建对象的实例,而不需要显式地调用构造函数。

List<Person> people = Arrays.asList(new Person("John", 25),new Person("Jane", 28)
);// 使用构造器引用简化对象的创建
List<Person> morePeople = people.stream().map(Person::new).collect(Collectors.toList());

5.6 数组和可变长参数

使用场景:Lambda表达式可以与数组和可变长参数结合使用,简化方法调用。

// 使用Lambda表达式和数组
Arrays.stream(new String[]{"Hello", "World"}).forEach(System.out::println);// 使用Lambda表达式和可变长参数
public static <T> void printAll(Consumer<T>... consumers) {for (Consumer<T> consumer : consumers) {consumer.accept(null);}
}printAll(System.out::println, System.err::println);

5.7 异常处理

使用场景:Lambda表达式可以与异常处理结合使用,使得错误处理更加简洁。

public <T> T processWithException(Function<String, T> func, String arg) {return func.apply(arg);
}public static void main(String[] args) {try {processWithException(s -> {if ("error".equals(s)) throw new IllegalArgumentException("Error!");return s.toUpperCase();}, "error");} catch (Exception e) {e.printStackTrace();}
}

5.8 闭包

使用场景:Lambda表达式支持闭包,允许Lambda表达式捕获并包含它们的上下文中的变量。

Function<Integer, Integer> adder = (initial) -> i -> i + initial;
Function<Integer> add5 = adder.apply(5);
System.out.println(add5.apply(10)); // 输出15

5.9 组合Lambda表达式

使用场景:Lambda表达式可以组合使用,形成复杂的逻辑链。

Function<String, Integer> toLength = String::length;
Function<Integer, Integer> increment = n -> n + 1;Function<String, Integer> processString = toLength.andThen(increment);
String input = "Lambda";
System.out.println(processString.apply(input)); // 输出7(字符串"Lambda"的长度加1)

6. 函数式接口的高级特性

Java 8不仅引入了函数式接口的概念,还为这些接口提供了一些高级特性,使得它们更加强大和灵活。这些特性包括默认方法、静态方法以及与方法引用和构造器引用的结合使用。本章节将详细介绍这些高级特性,并提供丰富的示例来展示它们的应用。

6.1 默认方法

默认方法允许接口提供默认实现的方法,这使得我们可以在不破坏现有实现的情况下,向接口添加新的方法。

使用场景:当需要向现有接口添加新功能,同时又不想让现有实现者进行大量修改时。

@FunctionalInterface
interface MyFunctionalInterface {default void defaultMethod() {System.out.println("Default method implementation");}
}MyFunctionalInterface myInterface = () -> {// 特定实现
};
myInterface.defaultMethod(); // 调用默认方法

6.2 静态方法

静态方法允许接口提供工具方法,这些方法可以在接口本身上直接调用,而不需要实例化接口。

使用场景:当需要提供一些与接口功能相关的工具方法时。

@FunctionalInterface
interface Converter<F, T> {static <F, T> Converter<F, T> identity() {return (f) -> f;}T convert(F from);
}Converter<String, Integer> converter = Converter.identity();
Integer result = converter.convert("123"); // 使用静态方法identity()创建的转换器

6.3 默认方法与Lambda表达式的结合

默认方法可以与Lambda表达式结合使用,提供灵活的行为。

使用场景:当需要在Lambda表达式中使用接口的默认方法时。

@FunctionalInterface
interface Processor {default void process() {System.out.println("Processing");}void perform();
}Processor processor = () -> {System.out.println("Performing a task");
}::process;processor.perform(); // 调用Lambda表达式中的perform方法
processor.process(); // 调用接口的默认方法process

6.4 静态方法与Lambda表达式的结合

静态方法可以与Lambda表达式结合使用,创建更加灵活和强大的工具。

使用场景:当需要在Lambda表达式中使用接口的静态方法时。

@FunctionalInterface
interface MathOperation {static MathOperation add(int a, int b) {return (x) -> x + a + b;}int operate(int x);
}MathOperation addFive = MathOperation.add(2, 3);
int result = addFive.operate(10); // 输出23

6.5 链式调用

通过默认方法和静态方法,可以实现链式调用,使得代码更加流畅。

使用场景:当需要创建一个流畅的API,允许调用者以链式的方式调用多个方法时。

@FunctionalInterface
interface FluentProcessor {default FluentProcessor next() {System.out.println("Next step in the process");return this;}default void start() {System.out.println("Starting the process");next();}
}FluentProcessor fp = new FluentProcessor() {// 具体实现
};fp.start().next(); // 链式调用start和next

6.6 方法引用与构造器引用

方法引用和构造器引用可以与默认方法和静态方法结合,简化代码。

使用场景:当需要在Lambda表达式中引用已有的方法或构造器时。

@FunctionalInterface
interface Action {void perform();
}Action action = this::method; // 方法引用class MyClass {void method() {System.out.println("Method called");}
}// 构造器引用
Function<String, MyClass> constructor = MyClass::new;
MyClass myClass = constructor.apply("Parameter");

相关文章:

函数式接口:现代编程的利器

1. 引言 在软件开发的演进过程中&#xff0c;函数式编程&#xff08;Functional Programming, FP&#xff09;逐渐显露头角&#xff0c;成为解决复杂问题的有效工具之一。函数式接口作为函数式编程的核心概念之一&#xff0c;其重要性不言而喻。本文将深入探讨函数式接口的概念…...

2022职称继续教育--深入实施新时代人才强国战略 加快建设世界重要人才中心和创新高地

单选题&#xff08;共7题&#xff0c;每题5分&#xff09; 1、&#xff08;&#xff09;实行职位职级制工资为主。 D、中长线科研重要岗位人员 2、建设世界重要人才中心和创新高地有&#xff08;&#xff09;个阶段目标。 B、三 3、综合国力竞争说到底是&#xff08;&#xf…...

kube-prometheus-stack 识别 k8s 集群内所有的 ServiceMonitor 和 PrometheusRule

默认情况下&#xff0c;kube-prometheus-stack 只自己创建的 ServiceMonitor&#xff0c;如果 k8s 集群内有多个非 kube-prometheus-stack 创建的 ServiceMonitor&#xff0c;不会被识别到。PrometheusRule 同理。 要识别所有的 ServiceMonitor 和 PrometheusRule &#xff0c;…...

Android 图片加载glide库 一次通关

前言 Glide是一个由Bumptech开发的开源图片加载库&#xff0c;专门用于Android平台。它被广泛应用于Android应用中&#xff0c;以简化图片加载过程&#xff0c;并提高性能和效率。 Glide能够快速加载图片&#xff0c;同时减少页面加载时间和内存消耗。Glide具有强大的缓存机制…...

Spring OAuth2:开发者的安全盾牌!(上)

何利用Spring OAuth2构建坚不可摧的安全体系&#xff1f;如何使用 OAuth2 从跨域挑战到性能优化&#xff0c;每一个环节都为你的应用保驾护航&#xff1f; 文章目录 Spring OAuth2 详解1. 引言简述OAuth2协议的重要性Spring Framework对OAuth2的支持概述 2. 背景介绍2.1 OAuth2…...

设计模式使用(成本扣除)

前言 名词解释 基础名词 订单金额&#xff1a;用户下单时支付的金额&#xff0c;这个最好理解 产品分成&#xff1a;也就是跟其他人合做以后我方能分到的金额&#xff0c;举个例子&#xff0c;比如用户订单金额是 100 块&#xff0c;我方的分成是 80%&#xff0c;那么也就是…...

输入输出(2)——C++的标准输出流

目录 一、C的标准输出流 &#xff08;一&#xff09;cout、cerr和clog流对象 1、cout 流对象 2、cerr 流对象 3、clog流对象 &#xff08;二&#xff09;用函数put输出字符 &#xff08;三&#xff09;用函数 write 输出字符 一、C的标准输出流 标准输出流——流向标准输…...

C语言序列化和反序列化--TPL(一)

TPL TPL说明网站 C语言中高效的序列化 您可以使用tpl快速轻松地存储和重新加载C数据。Tpl是一个用于序列化C数据的库。数据以自然二进制形式存储。该API很小&#xff0c;并试图保持“不碍事”。Tpl可以序列化许多C数据类型&#xff0c;包括结构。Tpl与文件、内存缓冲区和文件…...

Session + JWT + Cookie

00&#xff1a;HTTP无状态&#xff08;为了保持状态&#xff0c;前端好麻烦&#xff0c;又要自己存&#xff0c;又要想办法带出去&#xff0c;于是使用cookie&#xff09; 01&#xff1a;Cookie 将用户信息&#xff0c;在每次请求时候 带给后端&#xff08;但是自己存储大小有…...

PaddleOCR2.7+Qt5

章节一&#xff1a;Windows 下的 PIP 安装 官网安装教程地址 按照里面的教程去安装 如果使用cuda版本的还要安装tensorrt&#xff0c;不然后面运行demo程序的程序会报如下错。 下载TensorRT 8版本&#xff0c;tensorrt下载地址 章节二&#xff1a;编译源码 进入官网源码地址 下…...

在Android中解析XML文件并在RecyclerView中显示

1. 引言 最近工作有解析外部xml文件在App中显示的需求&#xff0c;特来写篇文章记录一下&#xff0c;方便下次使用。 2. 准备工作 首先&#xff0c;在项目的AndroidManifest.xml文件中添加读取外部存储的权限声明。 <uses-permission android:name"android.permiss…...

Notes for video: EDC-Con 2022/01 - EDC Conceptual Overview and Architecture

Eclipse Dataspace Connector 中文概念 Eclipse Dataspace Connector (EDC) 是一个开源项目&#xff0c;旨在提供一种标准化的方法来连接和共享数据空间中的数据。它是 Eclipse Foundation 下的一个项目&#xff0c;目标是促进数据共享和数据交换的互操作性。以下是 EDC 的一些…...

windows下nginx配置https证书

1、制作证书 1.1 安装工具openSSL。下载地址&#xff1a;http://slproweb.com/products/Win32OpenSSL.html Win64OpenSSL_Light-3_1_0.exe安装&#xff08;假定安装位置在 d:\openSSL\&#xff09; 1.2 配置openSSL环境。 新建系统变量OpenSSL值为d:\openSSL\bin&#xff0c;相…...

Llama改进之——RoPE旋转位置编码

引言 旋转位置编码(Rotary Position Embedding, RoPE)将绝对相对位置依赖纳入自注意力机制中&#xff0c;以增强Transformer架构的性能。目前很火的大模型LLaMA、QWen等都应用了旋转位置编码。 之前在[论文笔记]ROFORMER中对旋转位置编码的原始论文进行了解析&#xff0c;重点…...

Python的解析网页

课前案例 通过requests模块爬取指定网站中的图片并保存到本地目录中。 上述案例采用的是同步方式下载图片&#xff0c;效率太低。异步方式如下&#xff08;线程&#xff09;&#xff1a; # target为目标函数&#xff1b;args中传入的是download函数的参数url threading.Threa…...

VBA技术资料MF159:实现某个区域内的数据滚动

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…...

开源DMS文档管理系统 Nuxeo Vs Alfresco对比及 API 使用概述

1. 文档管理系统是什么 文档管理系统&#xff08;DMS&#xff1a;Document Management System&#xff09;是一种软件系统&#xff0c;用于组织、存储、检索和管理电子文档和文件。这些文件可以是各种格式的电子文档&#xff0c;如文本文档、电子表格、图像、音频或视频文件等…...

lambda函数实践

文章目录 1.简单实例2.lambda函数使用3.捕获列表的使用4.lambda表达式的应用1.简单实例 2.lambda函数使用 3.捕获列表的使用 4.lambda表达式的应用 #include <iostream> #include <vector>using namespace std;/** 1.简单实例* 2.lambda函数使用* 3.捕获列表的…...

[leetcode hot 150]第一百九十一题,位1的个数

题目&#xff1a; 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中设置位的个数&#xff08;也被称为汉明重量&#xff09;。 这道题比较简单&#xff0c;直接对最后一位进行与1的与操作&#xff0c;然…...

gitea的git库备份与恢复

文章目录 gitea库的备份与恢复概述笔记实验环境更新git for windows更新 TortoiseGit备份已经存在的gitea的git库目录使用gitea本身来备份所有git库目录将gitea库恢复到新目录m1m2m3启动gitea - 此时已经恢复完成FETCH_HEAD 中有硬写位置再查一下app.ini, 是否改漏了。m1m2 总结…...

【强化学习05】从Q学习到深度Q学习

深度Q学习&#xff08;Deep Q-Learning, DQN&#xff09;是将深度学习与Q学习结合起来的一种强化学习方法&#xff0c;利用神经网络来近似Q值函数&#xff0c;解决传统Q学习在大规模或连续状态空间中的局限性。下面详细解释DQN的机理。 背景知识 Q学习 Q学习是一种值函数法&…...

FPGA实现多路并行dds

目录 基本原理 verilog代码 仿真结果​ 基本原理 多路并行dds&#xff0c;传统DDS的局限性在于输出频率有限。根据奈奎斯特采样定理&#xff0c;单路DDS的输出频率应小于系统时钟频率的一半。但是在很多地方&#xff0c;要使采样率保持一致&#xff0c;所以&#xff0c;为了…...

ArcgisPro3.1.5安装手册

ArcgisPro3.1.5安装手册 一、目录介绍: 二、安装教程&#xff1a; (1)安装顺序&#xff1a;最先安装运行环境&#xff08;runtime6.0.5&#xff09;,接着安装install里面的文件&#xff0c;最后复制path里面的文件替换到软件bin文件夹下即可。 (2)具体安装步骤&#xff…...

三大主流框架

Web前端开发领域中&#xff0c;三大主流框架通常指的是&#xff1a; React&#xff1a;由Facebook开发的一个用于构建用户界面的JavaScript库。React以其组件化、声明式编程和虚拟DOM等特点而广受欢迎&#xff0c;能够高效地更新和渲染大型应用。 Vue.js&#xff1a;由尤雨溪创…...

【C++】:vector容器的底层模拟实现迭代器失效隐藏的浅拷贝

目录 &#x1f4a1;前言一&#xff0c;构造函数1 . 强制编译器生成默认构造2 . 拷贝构造3. 用迭代器区间初始化4. 用n个val值构造5. initializer_list 的构造 二&#xff0c;析构函数三&#xff0c;关于迭代器四&#xff0c;有关数据个数与容量五&#xff0c;交换函数swap六&am…...

必看项目|多维度揭示心力衰竭患者生存关键因素(生存分析、统计检验、随机森林)

1.项目背景 心力衰竭是一种严重的公共卫生问题,影响着全球数百万人的生活质量和寿命,心力衰竭的病因复杂多样,既有个体生理因素的影响,也受到环境和社会因素的制约,个体的生活方式、饮食结构和医疗状况在很大程度上决定了其心力衰竭的风险。在现代社会,随着生活水平的提…...

centos安装Redis

在CentOS上安装Redis的步骤如下&#xff1a; 使用yum安装依赖库&#xff1a; sudo yum install -y gcc make 下载Redis源码&#xff1a; wget http://download.redis.io/releases/redis-6.0.9.tar.gz 解压Redis源码&#xff1a; tar xzf redis-6.0.9.tar.gz 编译Redis&…...

继承与多态2

2.5&#xff08;杨.丹尼尔梁英文第11版P537&#xff1a;*13.12&#xff09;&#xff08;几何对象的面积求和&#xff09;写一个方法&#xff0c;将数组中所有几何对象的面积求和。 方法签名是: 公共静态双求和区域&#xff08;几何对象【】a&#xff09; 编写一个测试程序&…...

在RT-Thread下为MPU手搓以太网MAC驱动-3

文章目录 MAC驱动支持不同的PHY芯片关于对PHY设备抽象的改进RT-Thread下PHY设备抽象接口的改进关于对PHY设备抽象的改进 这是个人驱动开发过程中做的一些记录&#xff0c;仅代表个人意见和理解&#xff0c;不喜勿喷 MAC驱动需要支持不同的PHY芯片 MAC驱动支持不同的PHY芯片 关…...

Cocos Creator 2D物理引擎的使用详解

前言 Cocos Creator是一款优秀的游戏开发工具&#xff0c;它提供了强大的2D物理引擎&#xff0c;帮助开发者轻松实现游戏中的物理效果。在本文中&#xff0c;我们将详细介绍Cocos Creator中2D物理引擎的使用方法&#xff0c;并通过代码实现来演示其具体应用。 对惹&#xff0…...