告别冗长代码:Java Lambda 表达式如何简化你的编程

在现代软件开发中,高效和简洁的代码变得越来越重要。Java作为一门成熟而广泛使用的编程语言,一直在不断进化,以满足开发者的需求。Java 8的推出标志着一次重要的飞跃,其中最引人注目的特性之一便是Lambda表达式。

Lambda表达式为Java带来了函数式编程的灵活性,使得代码不仅更加简洁,还大大提升了可读性和维护性。不再需要冗长的匿名类,开发者可以用更少的代码完成更多的功能。对于那些致力于编写高效、简洁代码的开发者来说,掌握Lambda表达式是不可或缺的技能。

在本篇文章中,我们将深入探讨Java的Lambda表达式,揭示它的强大功能和应用场景。无论你是Java的初学者,还是有多年经验的老手,这篇文章都将带你领略Lambda表达式的魅力,帮助你在编程之旅中迈上新的台阶。


文章目录

        • 1、Lambda表达式概述
          • 1.1、Lambda表达式的简介
          • 1.2、Lambda 表达式的基本语法
          • 1.3、Lambda 表达式的基础示例
          • 1.4、Lambda表达式的要求
        • 2、函数式接口
          • 2.1、什么是函数式接口
          • 2.2、函数式接口的定义
          • 2.3、主要的函数式接口
            • 2.3.1、接口 `Predicate<T>`
            • 2.3.2、接口 `Consumer<T>`
            • 2.3.3、接口 `Function<T, R>`
            • 2.3.4、接口 `Supplier<T>`
            • 2.3.5、接口 `BiConsumer<T, U>`
            • 2.3.6、接口 `BiFunction<T, U, R>`
            • 2.3.7、接口 `UnaryOperator<T>`:
            • 2.3.8、接口 `BinaryOperator<T>`:
        • 3、Lambda 方法引用
          • 3.1、Lambda 方法引用的介绍
          • 3.2、静态方法引用
          • 3.3、实例方法引用
          • 3.4、特定类型的任意对象的实例方法引用
          • 3.5、构造器引用
        • 4、Lambda 变量捕获
          • 4.1、变量捕获的类型
          • 4.2、什么是 Effectively Final?
          • 4.3、示例:捕获局部变量
          • 4.4、不可以捕获的情况
          • 4.5、捕获实例变量
        • 5、Lambda 在集合当中的使用
          • 5.1、`Collection` 新增接口
          • 5.2、`List` 新增接口
          • 5.3、`Set` 新增接口
          • 5.4、`Map` 新增接口


1、Lambda表达式概述
1.1、Lambda表达式的简介

Java(SE)8 于 2014 年 3 月发布,引入了多个改进特性,其中 Lambda 表达式(Lambda expression,也可称为闭包(Closure))是最受欢迎的新特性之一。

Lambda 表达式允允许把函数作为一个方法的参数,允许在方法中传递代码块,从而实现更加灵活的编程方式。Lambda 表达式可以简化代码,减少样板代码的出现,并且使代码更加易读和易于维护。

Lambda 表达式允许我们通过表达式来代替功能接口。Lambda 表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。

Lambda 表达式为 Java 添加了函数式编程的能力,简化了代码,使得编写简洁的代码成为可能。这一特性特别适用于对集合进行操作的场景。

1.2、Lambda 表达式的基本语法

Lambda 表达式基本上是一个简洁的表示匿名函数的方法,它不需要像匿名类那样繁琐。Lambda 表达式的语法如下:

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

image-20230707105839045

其中 Lambda 表达式的三个组成部分:

  1. 参数列表(parameters):类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明,也可不声明而由 JVM 隐含的推断。另外如果只有一个参数,圆括号也可以省略;
  2. 箭头(->):连接参数列表和 Lambda 主体,可理解为 “被用于” 的意思;
  3. Lambda 主体(expression 或 { statements; }):可以是表达式也可以代码块,是函数式接口里方法的实现。①、expression:表达式,当 Lambda 体只有一条语句时可以是一个表达式或一个单独的语句;②、statements:代码块,如果 Lambda 体包含多条语句,需要用花括号括起来。③、无论是表达式还是代码块,都可以返回一个值或者什么都不反回。
1.3、Lambda 表达式的基础示例

假设我们有一个字符串列表,我们想要对其排序。使用 Lambda 表达式前后的代码对比如下:

使用传统方法(匿名内部类):

List<String> names = Arrays.asList("Peter", "Anna", "Mike", "Xenia");

Collections.sort(names, new Comparator<String>() {
    public int compare(String a, String b) {
        return a.compareTo(b);
    }
});

匿名内部类: 这里 new Comparator<String>() {...} 创建了一个 Comparator<String> 的匿名实现类。匿名内部类是没有类名的类,直接用其父类或要实现的接口作为其类型。

使用 Lambda 表达式:

List<String> names = Arrays.asList("Peter", "Anna", "Mike", "Xenia");

Collections.sort(names, (String a, String b) -> {
    return a.compareTo(b);
});

--- 或者更简洁

Collections.sort(names, (a, b) -> a.compareTo(b));
1.4、Lambda表达式的要求

虽然说,Lambda 表达式可以在⼀定程度上简化接口的实现。但是,并不是所有的接口都可以使用 Lambda 表达式来简洁实现的。

Lambda 表达式毕竟只是⼀个匿名方法。当实现的接口中的方法过多或者多少的时候,Lambda 表达式都是不适用的。

Lambda 表达式,只能实现函数式接口。


2、函数式接口
2.1、什么是函数式接口

在 Java 中,函数式接口(Functional Interface)是指具有单一抽象方法的接口,但它可以有多个默认(default)或静态(static)方法。Java 8 引入了这个概念,主要是为了支持 Lambda 表达式,同时保持对老代码的兼容性。

函数式接口的特性:

  • 单一抽象方法:这是函数式接口的核心特征,它意味着该接口中只有一个没有实现的方法;
  • 默认方法:Java 8 允许在接口中实现方法,这些方法被称为默认方法。默认方法不影响接口的"函数式接口"状态,因为它们不是抽象的;
  • 静态方法:接口还可以包含静态方法。这些方法同样不影响接口的函数式接口状态,因为静态方法也是具体实现的。

函数式接口提供了一种将功能逻辑作为数据传递的方式,极大地增强了 Java 在编写高效且简洁代码方面的能力。随着 Java 版本的迭代,函数式编程已成为开发中不可或缺的工具。

2.2、函数式接口的定义

在 Java 中,函数式接口通常通过 @FunctionalInterface 注解来表示。这个注解不是必需的,但它可以帮助编译器检查所标注的接口是否满足函数式接口的条件。标准的定义如下:

@FunctionalInterface
public interface MyFunctionalInterface {
    void execute();
}
2.3、主要的函数式接口

Java 8 引入了 java.util.function 包,这个包中定义了一系列的内建函数式接口,极大地方便了函数式编程的实践,特别是与 Lambda 表达式的结合使用。

2.3.1、接口 Predicate<T>

用途:Predicate<T> 接口定义一个参数的方法,返回布尔值。这通常用于判断或过滤数据。

方法签名:boolean test(T t);

示例:使用 Predicate<T> 过滤一个 List<String>,移除不符合条件的元素。

List<String> names = Arrays.asList("Peter", "Anna", "Mike", "Xenia");
// 移除以"M"开头的名字
names.removeIf(name -> name.startsWith("M"));
2.3.2、接口 Consumer<T>

用途:Consumer<T> 接口定义单一输入参数的 accept 方法,不返回任何结果(void 返回类型),常用于在对象上执行某些操作,如打印数据。

方法签名:void accept(T t);

示例:使用 Consumer<T> 打印 List 中的每个元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.forEach(number -> System.out.println(number));
2.3.3、接口 Function<T, R>

用途:Function<T, R> 接口定义一个接受一个参数并产生结果的方法,常用于映射或转换数据。

方法签名:R apply(T t);

示例:将字符串转换为其长度。

List<String> names = Arrays.asList("Peter", "Anna", "Mike", "Xenia");
List<Integer> nameLengths = names.stream()
    .map(name -> name.length())
    .collect(Collectors.toList());
2.3.4、接口 Supplier<T>

用途:Supplier<T> 不接受任何参数但返回一个值,并且这个值的类型是泛型 T。它常用于延迟生成或提供值的场景。

方法签名:T get();

示例:提供当前时间的字符串格式。

Supplier<String> currentTime = () -> new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Current Time: " + currentTime.get());
2.3.5、接口 BiConsumer<T, U>

用途:接受两个输入参数,无返回结果,用于两元素的操作。

方法签名:void accept(T t, U u);

示例:打印两个参数的和。

BiConsumer<Integer, Integer> add = (a, b) -> System.out.println("Sum: " + (a + b));
// 输出 Sum: 8
add.accept(5, 3);  
2.3.6、接口 BiFunction<T, U, R>

用途:接受两个输入参数,返回一个结果,用于两元素的操作。

方法签名:R apply(T t, U u);

示例:计算两个参数的和。

BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
// 计算 1+2 的结果
Integer sum = add.apply(1, 2);  
2.3.7、接口 UnaryOperator<T>

用途:一种特殊类型的 Function,输入参数类型和返回类型相同。

方法:T apply(T t);

示例:计算参数的平方并返回。

UnaryOperator<Integer> square = x -> x * x;
Integer result = square.apply(5);
2.3.8、接口 BinaryOperator<T>

用途:一种特殊类型的 BiFunction,其中两个输入参数和返回类型都相同。

方法:T apply(T t1, T t2);

示例:计算两个参数的积并返回。

BinaryOperator<Integer> multiply = (a, b) -> a * b;
Integer product = multiply.apply(5, 3); 

3、Lambda 方法引用
3.1、Lambda 方法引用的介绍

在 Java 中,方法引用是一种简化 lambda 表达式的写法,特别是当 lambda 表达式只是直接调用一个已存在的方法时。方法引用提供了一种更清晰、更简洁的方式来引用直接已存在的方法或构造器。

方法引用有四种主要的类型:

  1. 静态方法引用(ClassName::methodName);
  2. 实例方法引用(instance::methodName);
  3. 特定类型的任意对象的实例方法引用(ClassName::methodName);
  4. 构造器引用(ClassName::new)
3.2、静态方法引用

如果函数式接口的实现通过调用一个静态方法来完成,可以使用静态方法引用。

示例:

假设我们有以下静态方法:

public class MathOperations {
    public static int multiplyByTwo(int i) {
        return i * 2;
    }
}

我们可以这样使用方法引用替代相应的 lambda 表达式:

Function<Integer, Integer> timesTwo = MathOperations::multiplyByTwo;
// 输出 10
System.out.println(timesTwo.apply(5));  
3.3、实例方法引用

当目标引用是一个实例的方法时,可以使用实例方法引用。

示例:

假设有一个非静态方法:

public class Printer {
    public void printUpperCase(String s) {
        System.out.println(s.toUpperCase());
    }
}

使用实例方法引用:

Printer printer = new Printer();
Consumer<String> printUpper = printer::printUpperCase;
// 输出 HELLO
printUpper.accept("hello");  
3.4、特定类型的任意对象的实例方法引用

如果方法引用是针对特定类型的任意对象,可以使用 ClassName::methodName。

示例:

Function<String, String> upperFunct = String::toUpperCase;
// 输出 HELLO
System.out.println(upperFunct.apply("hello"));

这里,我们引用了 String 类的 toUpperCase 方法。

3.5、构造器引用

构造器引用与方法引用类似,但它调用的是类的构造器。

示例:

假设我们有以下类:

public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "'}";
    }
}

使用构造器引用:

Function<String, Person> personCreator = Person::new;
Person p = personCreator.apply("John Doe");
 // 输出 Person{name='John Doe'}
System.out.println(p); 

4、Lambda 变量捕获

Lambda 表达式与匿名内部类相似,它们都可以访问"外围"作用域中的变量。这种访问外围变量的行为称为"变量捕获"。

4.1、变量捕获的类型

在 Lambda 表达式中,可以捕获两种类型的变量:

  1. 实例变量和静态变量:Lambda 表达式内部可以自由使用实例变量和静态变量而不受任何限制,这些变量可以自由地被读取或修改;

  2. 局部变量:可以捕获外围方法的局部变量,但这些局部变量必须是事实上的最终变量(effectively final),即这些变量在初始化后不会再为它们赋新值。

4.2、什么是 Effectively Final?

一个变量如果被声明为 final,那么它就是最终变量。即使变量没有被声明为 final,但在初始化后从未改变过,那么这个变量也是事实上的最终变量。从 Java 8 开始,这样的未声明为 final 的变量也可以在 Lambda 表达式中被捕获。

4.3、示例:捕获局部变量
public class LambdaCaptureExample {
    public static void main(String[] args) {
        int num = 10;
      	// Effectively final variable
        Runnable r = () -> System.out.println(num);
      	// 输出 10
        r.run();
    }
}

在这个例子中,变量 num 虽然没有被声明为 final,但在初始化之后没有再改变,所以它是事实上的最终变量,可以在 Lambda 表达式中被安全捕获。

4.4、不可以捕获的情况

如果尝试在 Lambda 表达式中捕获一个不是事实上的最终变量,编译器将会报错:

public class LambdaCaptureExample {
    public static void main(String[] args) {
        int num = 10;
        num = 20;  
      	// 修改变量,使其不再是 effectively final
        Runnable r = () -> System.out.println(num);  // 编译错误
        r.run();
    }
}

因为 num 在初始化后被修改,它不是一个事实上的最终变量,因此不能被 Lambda 表达式捕获。

4.5、捕获实例变量

实例变量与静态变量不需要是事实上的最终变量,它们可以在 Lambda 表达式内部被修改:

public class LambdaCaptureExample {
    private static int staticNum = 5;
    private int instanceNum = 5;

    public void test() {
        Runnable r = () -> {
          	// 直接修改静态变量
            staticNum++;  
          	// 直接修改实例变量
            instanceNum++;
          	// 输出 12
            System.out.println(staticNum + instanceNum);  
        };
        r.run();
    }

    public static void main(String[] args) {
        new LambdaCaptureExample().test();
    }
}

5、Lambda 在集合当中的使用

Java 8 在 CollectionListSet、和 Map 接口中引入了多种新方法,这些方法大都利用 Lambda 表达式来提高编程效率和简化代码。

下面是这些接口中新增方法的详细介绍:

5.1、Collection 新增接口

Collection 接口是 ListSet 接口的父接口,因此在 Collection 中添加的方法也会影响到这两个接口。以下是新增的几个重要方法:

①、forEach(Consumer<? super T> action) 对每个元素执行指定的动作。这是内部迭代的一种形式,可以替代外部迭代(即使用 for-each 循环)

collection.forEach(System.out::println);

②、stream() 返回集合的顺序 Stream 表达形式,可以进行更复杂的聚合操作

collection.stream().filter(e -> e.startsWith("A")).forEach(System.out::println);

③、parallelStream() 返回集合的并行 Stream 表达形式,用于并行处理集合元素,适用于数据量大时的场景

collection.parallelStream().filter(e -> e.startsWith("A")).forEach(System.out::println);

④、removeIf(Predicate<? super E> filter) 根据指定的条件(Predicate 表达式)删除元素

// 删除所有空元素
collection.removeIf(e -> e.isEmpty());

⑤、spliterator() 提供了一种创建可分割迭代器(Spliterator)的方法,适用于 Stream 的并行分解

Spliterator<T> spliterator = collection.spliterator();
5.2、List 新增接口

除了继承自 Collection 接口的方法外,List 接口特有的新增方法主要包括:

①、sort(Comparator<? super E> c) 根据指定的比较器对列表进行排序,此方法直接修改原列表

list.sort(Comparator.naturalOrder());

②、replaceAll(UnaryOperator<E> operator) 根据指定的函数应用运算,替换每个元素

// 将所有字符串元素转换为大写
list.replaceAll(String::toUpperCase);  
5.3、Set 新增接口

Set 接口没有特别的新增方法,它继承了 Collection 接口的所有新增方法,这包括 forEach, stream, parallelStream, removeIf, 和 spliterator

5.4、Map 新增接口

Map 接口在 Java 8 中增加了一系列非常有用的方法来简化常见的任务:

①、forEach(BiConsumer<? super K, ? super V> action) 对每个键值对执行指定的操作

map.forEach((key, value) -> System.out.println(key + ": " + value));

②、replaceAll(BiFunction<? super K, ? super V, ? extends V> function) 将每个元素替换为函数的结果

map.replaceAll((key, value) -> value.toUpperCase());

③、computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) 如果键对应的值为 null,则尝试计算新的映射,并插入到 Map

map.computeIfAbsent("key", k -> "New " + k);

④、computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) 如果键存在,则使用给定的重新映射函数计算其值

map.computeIfPresent("key", (k, v) -> v + " Updated");

⑤、compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) 对键进行重新计算,无论原来是否存在

map.compute("key", (k, v) -> (v == null) ? "New Value" : v + " Computed");

⑥、merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) 将键映射到给定值和当前值(如果已存在)的重新映射结果

map.merge("key", "New Value", (v1, v2) -> v1 + ", " + v2);

这些方法使得对集合进行操作更加灵活和强大,特别是在需要对集合进行批量操作、计算或条件更新时。通过这些工具,Java的集合库更加贴近现代编程需求,使得代码不仅更简洁,而且性能也有所提升。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker 进入指定容器内部(以Mysql为例)

文章目录 一、启动容器二、查看容器是否启动三、进入容器内部 一、启动容器 这个就不多说了 直接docker run… 二、查看容器是否启动 查看正在运行的容器 docker ps查看所有的容器 docker ps -a结果如下图所示&#xff1a; 三、进入容器内部 通过CONTAINER ID进入到容器…

linux命令别名与shell函数

# 修改网卡配置 alias vinetwork"vi /etc/sysconfig/network-scripts/ifcfg-ens33" 1. 方法和调用在同一个文件 # 定义shell函数,返回值通过$?获取 function say_hello(){ echo "hello shell" return 1 } # 使用shell函数 say_hello # 执行脚本后接收返…

zabbix-agent如何版本回退降低?

文章目录 1&#xff0c;查看zabbix-agent版本号2&#xff0c;查看zabbix-server的版本号3&#xff0c;卸载已有的zabbix-agent4&#xff0c;找到与zabbix-server匹配版本的zabbix-agent5&#xff0c;安装zabbix-agent 5.0.42版本6&#xff0c;查看已安装的zabbix-agent的版本号…

4秒惊艳!Stable Cascade AI绘画神器,设计师和普通用户的无限创意新选择

近日&#xff0c;一款AI绘画模型Stable Cascade发布。 只需输入一段描述文字&#xff0c;即可在4秒钟内获得令人惊艳的图像。 无论你是设计师、艺术家&#xff0c;还是普通用户&#xff0c;都能轻松上手&#xff0c;释放无限创意。 Stable Cascade不仅在使用上极具便捷性&am…

hot100_62不同路径

不同路径 题目思路、代码1.排列组合2.动态规划 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff0…

如何提升推广链接辨识度与可信度?试试自定义链接后缀

各位大佬&#xff0c;咱今天来聊聊短信营销这个事儿。这可是好多企业都在用的营销手段啊&#xff0c;一条几分钱的短信&#xff0c;就能搭起用户和企业的桥梁&#xff0c;能增强粘性、促成交易或者推动复购&#xff0c;那真是高覆盖、低成本、高效率。 但现在问题来了&#xf…

电商数据采集决策智慧:深度解析数据采集与应用||电商API数据采集接口的接入与应用

引言 在数字化时代&#xff0c;数据已成为电商企业最宝贵的资产之一。通过有效的数据采集&#xff0c;企业能够洞察市场动态、理解消费者需求、优化运营策略&#xff0c;从而在激烈的市场竞争中脱颖而出。本文将深入探讨电商数据采集的重要性、常用方法以及应用实践。 一、电…

Hadoop3:MapReduce工作流程图解

一、流程图 二、流程说明 上面的流程是整个MapReduce最全工作流程&#xff0c;但是Shuffle过程只是从第7步开始到第16步结束&#xff0c;具体Shuffle过程详解&#xff0c;如下&#xff1a; &#xff08;1&#xff09;MapTask收集我们的map()方法输出的kv对&#xff0c;放到内存…

[AI OpenAI] 提取GPT-4中的概念

总结&#xff1a; 研究人员采用新的可扩展方法&#xff0c;将GPT-4的内部表示分解为1600万个通常可解释的模式&#xff0c;这些模式被称为“特征”&#xff0c;目的是提高语言模型的透明度和可解释性。通过使用稀疏自编码器&#xff0c;研究人员能够识别与特定概念相关的特征&…

【面试干货】索引的作用

【面试干货】索引的作用 1、索引的作用 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、索引的作用 索引 可以协助 快速查询、更新数据库表中数据。 通过使用索引&#xff0c;数据库系统能够快速定位到符合查询条件的数据&#xff0c;提…

第二证券炒股知识:北交所的股票是a股吗?是主板吗?

北交所的股票是a股&#xff0c;但不属于主板&#xff0c;是一个单独的板块。 A股主板是在上海证券买卖所或许深圳证券买卖所上市的公司&#xff0c;主板通常是大盘股&#xff0c;多为商场占有率高、规划大、盈余安稳良好的大型企业。沪市主板以600、601或603最初&#xff0c;深…

Game Fi链游:定制开发源码搭建

随着科技的飞速发展&#xff0c;游戏开发行业正经历着前所未有的变革。Game Fi&#xff0c;这个新兴的概念&#xff0c;正以其独特的魅力&#xff0c;引发了游戏开发行业的热潮。 一、Game Fi 的概念与影响 Game Fi&#xff0c;是一种新型的游戏开发模式&#xff0c;它强调游…

从0到1实现一个自己的大模型,实践中了解模型流程细节

前言 最近看了很多大模型&#xff0c;也使用了很多大模型。对于大模型理论似乎很了解&#xff0c;但是好像又缺点什么&#xff0c;思来想去决定自己动手实现一个 toy 级别的模型&#xff0c;在实践中加深对大语言模型的理解。 在这个系列的文章中&#xff0c;我将通过亲手实践…

Django项目部署(命令函部署)

Django项目搭建 一. 下载宝塔面板 我这里使用的是命令函部署 , 下载宝塔主要为了是方便操作 , 宝塔的终端支持复制粘贴 , 而且可以帮助我们快速的检索文件目录以及避免一些软件的环境配置 下载方法: ​ 打开浏览器访问 : 宝塔面板下载&#xff0c;免费全能的服务器运维软件…

智谱AI最新开源模型CHATGLM4-9B试用

智谱AI最近开源了GLM4-9B模型。之前已开源chatglm1到chatglm3&#xff0c;相比前面开源的相比GLM3-6B有了大幅度提升。本次开源基本的GLM4-9B&#xff0c;还开源了对话版GLM-4-9B-Chat&#xff0c; 多模态版GLM-4V-9B&#xff0c; 长文本版GLM-4-9B-Chat-1M。 在语义、数学、推…

解决nvidia驱动和CUDA升级问题

解决nvidia驱动和CUDA升级问题 注释&#xff1a;升级高版本的nvidia驱动和cuda是不影响现有的docker镜像和容器的。因为是向下兼容的。仅仅升级后重启服务器即可。 ERROR: An NVIDIA kernel module ‘nvidia-drm’ appears to already be loaded in your kernel. This may be…

git根据历史某次提交创建新分支

有时候项目在做版本管理的时候&#xff0c;忘记了创建某次版本的分支&#xff0c;而直接在主分支上进行开发了&#xff0c;这个时候&#xff0c;想要对某次提交单独拉出来一个版本分支&#xff0c;就需要用到这个功能&#xff1a; git checkout -b 新分支名 某次提交的id 找到…

全栈工程师之路 — 从零到精通Spring Boot -1

全栈工程师之路 — 从零到精通Spring Boot -1 Day 1: 项目初始化与依赖配置 课程详细介绍: 在第一天,我们将创建一个简单的Spring Boot项目,进行基本的初始化和依赖配置。我们将使用Maven子模块方式组织项目结构,并配置基本的依赖以支持后续学习。 示例代码: 创建父项…

QT Creator与QT的下载安装

0.起因/小结&#xff1a; 因为运行项目需要更高版本的QT。 下载了QT 6.2.0&#xff0c;但是里面的gcc&#xff0c;g&#xff0c;gdb是64bit的&#xff0c;而我的QT Creator是32bit的&#xff0c;所以又下载了QT 13.0.0的64bit版本。 遇到问题&#xff1a;msvcp140_1.dll找不到…

轻兔推荐 —— hoppscotch

via&#xff1a;轻兔推荐 - https://app.lighttools.net/ 简介 hoppscotch是一个开源的http调试客户端&#xff0c;界面简洁&#xff0c;功能完善&#xff0c;原名叫postwomen&#xff0c;明显是要跟postman干的&#xff0c;作为postman的替代品就挺合适 - 功能完善&#xff…