简介:聚焦 Java 泛型这一“类型安全保障”核心技术,从泛型解决的核心痛点(非泛型代码的运行时类型错误、强制类型转换冗余)切入,详解泛型的本质(参数化类型)、核心用法(泛型类/接口/方法)、类型通配符(上界/下界/未限定)、类型擦除原理,以及泛型与继承的关系,结合 JDK8 特性(菱形语法、类型推断增强)与场景化代码示例,帮初学者理解泛型如何将类型错误提前到编译时,减少冗余代码,提升代码复用性与稳定性,为后续集合框架、通用组件开发夯实基础。

一、为什么用泛型?—— 解决非泛型的“痛点”

在泛型出现前,Java 用 Object 存储任意类型数据,导致两大问题:运行时类型错误(编译时无法检查类型)和强制类型转换冗余。泛型通过“参数化类型”,让类型成为代码的“参数”,从根本上解决这些问题,带来三大核心优势:

1. 编译时更强的类型检查

非泛型代码中,编译器无法验证集合存储的类型,错误只能在运行时暴露;泛型代码在编译时就会拦截类型不匹配的错误。

示例:非泛型 vs 泛型的类型检查

// 非泛型:编译通过,运行时抛ClassCastException
List nonGenericList = new ArrayList();
nonGenericList.add("Java");
nonGenericList.add(123); // 编译无错误(Object类型)
String s = (String) nonGenericList.get(1); // 运行时错误:Integer不能转String// 泛型:编译时直接报错,提前拦截错误
List<String> genericList = new ArrayList<>();
genericList.add("Java");
genericList.add(123); // 编译错误:不兼容的类型,int无法转String

2. 取消强制类型转换

非泛型代码中,从集合获取元素必须强制转换;泛型代码通过类型参数自动匹配,无需手动转换,减少代码冗余与错误风险。

示例:取消强制转换

// 非泛型:需强制转换
List nonGenericList = new ArrayList();
nonGenericList.add("Hello");
String s1 = (String) nonGenericList.get(0); // 必须强转// 泛型:无需转换,编译器自动匹配类型
List<String> genericList = new ArrayList<>();
genericList.add("Hello");
String s2 = genericList.get(0); // 直接获取,无强转

3. 实现泛型算法

泛型允许编写“与类型无关”的通用算法,可复用在不同类型集合上,且保证类型安全。例如,一个排序算法可同时处理 List<Integer>List<String>(只要元素可比较)。

示例:泛型算法(计算大于指定元素的数量)

// 泛型方法:适用于所有实现Comparable的类型
public static <T extends Comparable<T>> int countGreaterThan(T[] arr, T elem) {int count = 0;for (T e : arr) {if (e.compareTo(elem) > 0) { // 调用Comparable方法,类型安全count++;}}return count;
}// 调用:支持Integer、String等可比较类型
Integer[] intArr = {1, 3, 5, 7};
System.out.println(countGreaterThan(intArr, 3)); // 输出2(5、7)String[] strArr = {"a", "c", "e"};
System.out.println(countGreaterThan(strArr, "c")); // 输出1(e)

二、泛型类型:定义泛型类与接口

泛型类型是“参数化的类或接口”,通过 <类型参数> 声明,可在类/接口内部用作字段、方法参数或返回值类型。

1. 泛型类/接口的定义

语法:class/interface 名称<T1, T2, ...> { ... },其中 <T1, T2> 是类型参数(也叫类型变量),代表未知类型,后续可在类体中使用。

示例1:泛型类 Box

/*** 泛型Box类:存储任意类型的单个对象* @param <T> 存储对象的类型(Type)*/
public class Box<T> {private T content; // 类型参数作为字段类型// 类型参数作为构造函数参数类型public Box(T content) {this.content = content;}// 类型参数作为方法返回值和参数类型public T getContent() {return content;}public void setContent(T content) {this.content = content;}
}

示例2:泛型接口 Pair<K, V>

/*** 泛型接口:存储键值对* @param <K> 键的类型(Key)* @param <V> 值的类型(Value)*/
public interface Pair<K, V> {K getKey();V getValue();void setKey(K key);void setValue(V value);
}// 实现泛型接口
public class OrderedPair<K, V> implements Pair<K, V> {private K key;private V value;public OrderedPair(K key, V value) {this.key = key;this.value = value;}@Overridepublic K getKey() { return key; }@Overridepublic V getValue() { return value; }@Overridepublic void setKey(K key) { this.key = key; }@Overridepublic void setValue(V value) { this.value = value; }
}

2. 类型参数命名规范

按惯例,类型参数用单个大写字母,便于区分普通类名,常见命名:

  • E:元素(Element,集合框架常用,如 List<E>
  • K:键(Key,如 Map<K, V>
  • V:值(Value,如 Map<K, V>
  • T:类型(Type,通用类型参数)
  • S、U、V:第2、3、4个类型参数

3. 泛型类型的实例化

实例化泛型类时,需指定类型实参(替换类型参数的具体类型),JDK7+ 支持“菱形语法”(<>),编译器可自动推断类型。

示例:实例化泛型类

// JDK7前:需显式指定类型实参
Box<String> stringBox1 = new Box<String>("Java泛型");// JDK7+:菱形语法,编译器从左側推断类型
Box<String> stringBox2 = new Box<>("Java菱形语法");// 多个类型参数的实例化
Pair<String, Integer> user = new OrderedPair<>("Alice", 25);
System.out.println("Name: " + user.getKey() + ", Age: " + user.getValue());

4. 原始类型与未检查警告

  • 原始类型:泛型类/接口不带类型参数的形式(如 Box 而非 Box<T>),是为兼容 pre-JDK5 代码保留的特性。
  • 问题:原始类型绕过泛型类型检查,可能导致运行时错误,且编译器会生成“未检查警告”。
  • 建议:除非必须兼容旧代码,否则避免使用原始类型;若无法避免,可通过 @SuppressWarnings("unchecked") 抑制警告(需确保代码安全)。

示例:原始类型的风险

// 原始类型:编译器警告“使用了未经检查或不安全的操作”
Box rawBox = new Box(123);
// 错误:将String赋值给原始类型Box,编译无警告,运行时错误
rawBox.setContent("错误类型");
Integer content = (Integer) rawBox.getContent(); // 运行时ClassCastException

三、泛型方法:定义通用方法

泛型方法是“自身声明类型参数的方法”,类型参数作用域仅限于当前方法,支持静态/非静态方法,甚至构造函数。

1. 泛型方法的定义

语法:[修饰符] <T1, T2, ...> 返回值类型 方法名(参数列表) { ... }类型参数声明必须在返回值类型前

示例1:静态泛型方法(比较两个Pair是否相等)

public class PairUtil {/*** 静态泛型方法:比较两个Pair的键和值是否相等* @param <K> 键类型* @param <V> 值类型* @param p1 第一个Pair* @param p2 第二个Pair* @return 相等返回true,否则false*/public static <K, V> boolean equals(Pair<K, V> p1, Pair<K, V> p2) {return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue());}
}// 调用:编译器自动推断类型参数为<String, Integer>
Pair<String, Integer> p1 = new OrderedPair<>("Alice", 25);
Pair<String, Integer> p2 = new OrderedPair<>("Alice", 25);
System.out.println(PairUtil.equals(p1, p2)); // 输出true

示例2:非静态泛型方法(Box的泛型构造函数)

public class Box<T> {private T content;// 泛型构造函数(虽未显式声明<T>,但使用类的类型参数)public Box(T content) {this.content = content;}// 非静态泛型方法:转换Box的类型public <U> Box<U> convert(U newContent) {return new Box<>(newContent);}
}// 调用非静态泛型方法
Box<String> stringBox = new Box<>("Java");
Box<Integer> intBox = stringBox.convert(123); // 推断U为Integer

2. 类型推断

编译器可根据方法参数、目标类型自动推断泛型方法的类型参数,无需显式指定(显式指定格式:类名.<T>方法名(参数))。

示例:类型推断的简化调用

// 显式指定类型参数(不推荐,冗余)
boolean eq1 = PairUtil.<String, Integer>equals(p1, p2);// 编译器自动推断类型(推荐,简洁)
boolean eq2 = PairUtil.equals(p1, p2);// 目标类型驱动的类型推断(JDK8+)
List<String> list = Collections.emptyList(); // 推断为List<String>

3. 有限类型参数(边界约束)

默认情况下,类型参数可代表任何引用类型(如 T 等价于 T extends Object)。通过 extends 关键字可限制类型参数的上界(只能是指定类型或其子类型),支持多个边界(类在前,接口在后,用 & 分隔)。

示例1:单边界(T 必须实现 Comparable)

// 有限类型参数:T必须实现Comparable<T>(可比较)
public static <T extends Comparable<T>> T max(T a, T b) {return a.compareTo(b) > 0 ? a : b;
}// 调用:支持Integer、String等实现Comparable的类型
System.out.println(max(3, 5)); // 输出5
System.out.println(max("apple", "banana")); // 输出"banana"

示例2:多边界(T 必须是 Number 子类且实现 Serializable)

// 多边界:T extends 类 & 接口1 & 接口2(类必须在前)
public static <T extends Number & Serializable> void print(T num) {System.out.println("Value: " + num + ", Class: " + num.getClass().getSimpleName());
}// 调用:Integer是Number子类且实现Serializable
print(123); // 输出"Value: 123, Class: Integer"

四、泛型与继承:避免子类型误解

泛型不遵循“类型实参的继承关系”,即若 AB 的子类,List<A> 不是 List<B> 的子类,这是泛型类型安全的关键。

1. 泛型子类型的误区

错误认知IntegerNumber 的子类 → List<Integer>List<Number> 的子类。
正确结论List<Integer>List<Number> 无继承关系,共同父类是 List<?>(通配符类型)。

示例:泛型子类型的错误与后果

List<Integer> intList = new ArrayList<>();
// 编译错误:List<Integer>不能赋值给List<Number>
List<Number> numList = intList; // 若允许赋值,会导致类型安全问题(实际存储Integer的列表存入Double)
numList.add(3.14); // 编译无错,但intList实际存储了Double
Integer num = intList.get(0); // 运行时ClassCastException

2. 通配符:灵活构建泛型子类型关系

通配符(?)代表“未知类型”,通过结合 extends(上界)和 super(下界),可灵活构建泛型类型间的关系,解决泛型子类型的灵活性问题。

(1)上界通配符:? extends T

代表“未知类型,且是 TT 的子类”,适用于**“输入”变量**(仅读取,不写入,除非写入 null)。

示例:上界通配符计算数字列表总和

// 上界通配符:list元素是Number或其子类(Integer、Double等)
public static double sumOfList(List<? extends Number> list) {double sum = 0.0;for (Number num : list) {sum += num.doubleValue(); // 调用Number的方法,类型安全}return sum;
}// 调用:支持List<Integer>、List<Double>等
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
System.out.println(sumOfList(intList)); // 输出6.0
System.out.println(sumOfList(doubleList)); // 输出6.6
(2)下界通配符:? super T

代表“未知类型,且是 TT 的超类”,适用于**“输出”变量**(可写入 T 或其子类,读取时仅能当作 Object)。

示例:下界通配符向列表添加整数

// 下界通配符:list元素是Integer或其超类(Number、Object)
public static void addNumbers(List<? super Integer> list) {for (int i = 1; i <= 3; i++) {list.add(i); // 写入Integer,类型安全}
}// 调用:支持List<Integer>、List<Number>、List<Object>
List<Number> numList = new ArrayList<>();
addNumbers(numList);
System.out.println(numList); // 输出[1, 2, 3]
(3)未限定通配符:?

代表“未知类型”,适用于不依赖类型参数的操作(如获取列表大小、清空列表),或仅用 Object 方法访问元素。

示例:未限定通配符打印任意类型列表

// 未限定通配符:list元素类型未知,仅用Object方法
public static void printList(List<?> list) {for (Object elem : list) {System.out.print(elem + " ");}System.out.println();
}// 调用:支持任何类型的List
List<String> strList = Arrays.asList("a", "b", "c");
List<Integer> intList = Arrays.asList(1, 2, 3);
printList(strList); // 输出"a b c "
printList(intList); // 输出"1 2 3 "
(4)通配符使用指南
  • “输入”变量(仅读取):用 ? extends T(如 sumOfList);
  • “输出”变量(仅写入):用 ? super T(如 addNumbers);
  • 既读又写:不用通配符(直接用 List<T>);
  • 不依赖类型:用 ?(如 printList)。

五、类型擦除:泛型的实现原理

Java 泛型是“编译时技术”,运行时不存在泛型类型信息,编译器通过类型擦除实现泛型,确保兼容性且无运行时开销。

1. 类型擦除的过程

编译器对泛型代码执行以下操作:

  1. 替换类型参数:若类型参数有上界,替换为第一个上界;若无界,替换为 Object
  2. 插入类型转换:若需要,插入强制类型转换以保证类型安全;
  3. 生成桥接方法:若泛型类被继承,生成桥接方法保持多态性。

示例1:泛型类的擦除

// 泛型类Box<T>(无界)
public class Box<T> {private T content;public T getContent() { return content; }
}// 擦除后:T替换为Object
public class Box {private Object content;public Object getContent() { return content; }
}// 泛型类Box<T extends Comparable<T>>(有界)
public class Box<T extends Comparable<T>> {private T content;public T compare(T other) { return content.compareTo(other) > 0 ? content : other; }
}// 擦除后:T替换为第一个上界Comparable
public class Box {private Comparable content;public Comparable compare(Comparable other) { return content.compareTo(other) > 0 ? content : other; }
}

示例2:泛型方法的擦除

// 泛型方法countGreaterThan
public static <T extends Comparable<T>> int countGreaterThan(T[] arr, T elem) { ... }// 擦除后:T替换为Comparable
public static int countGreaterThan(Comparable[] arr, Comparable elem) { ... }

2. 桥接方法:保持泛型多态性

当泛型类被继承且方法被重写时,类型擦除可能导致方法签名不匹配,编译器会生成桥接方法(合成方法)解决此问题。

示例:桥接方法的产生

// 泛型父类Node<T>
public class Node<T> {public void setData(T data) { ... }
}// 子类MyNode继承Node<Integer>
public class MyNode extends Node<Integer> {@Overridepublic void setData(Integer data) { ... } // 重写setData
}// 擦除后:父类Node的setData变为setData(Object),子类MyNode的setData(Integer)不匹配
// 编译器生成桥接方法,委托给子类的setData(Integer)
public class MyNode extends Node {// 子类重写的方法public void setData(Integer data) { ... }// 编译器生成的桥接方法public void setData(Object data) {setData((Integer) data); // 强制转换后调用子类方法}
}

3. 堆污染与 @SafeVarargs

  • 堆污染:参数化类型变量引用非该类型的对象(如 List<String>[] arr = new List[2]; arr[0] = new List<Integer>();),通常由混合原始类型或未检查转换导致。
  • @SafeVarargs 注解:用于泛型可变参数方法,断言方法实现不会不当处理可变参数,抑制“潜在堆污染”警告。

示例:@SafeVarargs 的使用

public class ArrayUtil {// 泛型可变参数方法,用@SafeVarargs抑制警告@SafeVarargspublic static <T> void addAll(List<T> list, T... elements) {for (T elem : elements) {list.add(elem);}}public static void main(String[] args) {List<String> list = new ArrayList<>();addAll(list, "a", "b", "c"); // 安全调用,无警告}
}

六、泛型的限制:避免常见错误

泛型受限于 Java 语言特性,存在以下限制,需理解原因并规避:

限制原因示例(编译错误)
不能实例化类型参数类型擦除后类型参数消失,无法创建实例T elem = new T();
不能声明静态类型参数字段静态字段属于类,类型参数随实例变化,冲突public class Box<T> { private static T content; }
不能用 instanceof 检查泛型类型类型擦除后无泛型信息,无法区分if (list instanceof List<Integer>) { ... }
不能创建泛型类型数组数组运行时检查元素类型,泛型擦除后无法保证安全List<Integer>[] arr = new List<Integer>[2];
不能继承 Throwable异常处理需运行时类型信息,泛型擦除后无法匹配class MyException<T> extends Exception { ... }
不能重载擦除后签名相同的方法擦除后方法签名一致,编译器无法区分public void print(List<String> s) {} public void print(List<Integer> i) {}

七、问题与练习:巩固泛型知识

1. 基础问题解答

问题1:编写泛型方法,计算集合中符合特定属性的元素数量(如奇数、素数)。

解答:传入 Predicate<T> 接口(函数式接口),灵活指定属性:

import java.util.Collection;
import java.util.function.Predicate;public class GenericCounter {public static <T> int countMatching(Collection<T> coll, Predicate<T> predicate) {int count = 0;for (T elem : coll) {if (predicate.test(elem)) {count++;}}return count;}public static void main(String[] args) {Collection<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);// 统计奇数(Predicate用Lambda表达式)int oddCount = countMatching(nums, n -> n % 2 != 0);System.out.println("奇数数量:" + oddCount); // 输出3}
}
问题2:Algorithm 类的 max 方法能否编译?为什么?
public final class Algorithm {public static <T> T max(T x, T y) {return x > y ? x : y;}
}

解答:不能编译。T 是无界类型参数,默认是 Object 类型,Object 没有 > 运算符(仅原始类型支持),需添加边界 T extends Comparable<T>,用 compareTo 方法比较。

问题3:Singleton<T> 类能否编译?为什么?
public class Singleton<T> {public static T getInstance() {if (instance == null)instance = new Singleton<T>();return instance;}private static T instance = null;
}

解答:不能编译。静态字段 instance 属于类,而 T 是实例级别的类型参数,静态上下文无法访问实例类型参数,需移除泛型或调整设计(如用静态内部类)。

2. 动手练习:泛型方法交换数组元素

需求:编写泛型方法,交换数组中两个索引处的元素,支持任意类型数组。
实现

public class ArraySwapper {public static <T> void swap(T[] arr, int i, int j) {if (arr == null || i < 0 || j < 0 || i >= arr.length || j >= arr.length) {throw new IllegalArgumentException("无效参数");}T temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {Integer[] intArr = {1, 2, 3};swap(intArr, 0, 2);System.out.println(Arrays.toString(intArr)); // 输出[3, 2, 1]String[] strArr = {"a", "b", "c"};swap(strArr, 1, 2);System.out.println(Arrays.toString(strArr)); // 输出[a, c, b]}
}

八、总结:泛型是 Java 类型安全的“基石”

泛型通过“参数化类型”将类型错误从运行时提前到编译时,同时消除冗余的强制转换,让通用算法可安全复用在不同类型上。核心要点:

  1. 泛型类型:定义泛型类/接口,用 <T> 声明类型参数,实例化时用菱形语法简化;
  2. 泛型方法:类型参数声明在返回值前,支持类型推断和边界约束,实现通用逻辑;
  3. 通配符:上界(? extends T)用于输入,下界(? super T)用于输出,灵活处理泛型子类型;
  4. 类型擦除:编译时替换类型参数为边界或 Object,生成桥接方法保持多态;
  5. 限制规避:理解泛型的限制原因,避免实例化类型参数、静态类型字段等错误。

掌握泛型是学好 Java 集合框架、Spring 等框架的前提,也是编写类型安全、高复用代码的关键。后续学习集合(如 ArrayList<T>HashMap<K,V>)时,泛型的知识将帮助你更深刻理解其设计原理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/98052.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/98052.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/98052.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL和Redis的数据一致性问题与业界常见解法

一、为什么会出现数据不一致&#xff1f; 根本原因在于&#xff1a;这是一个涉及两个独立存储系统的数据更新操作&#xff0c;它无法被包装成一个原子操作&#xff08;分布式事务&#xff09;。更新数据库和更新缓存是两个独立的步骤&#xff0c;无论在代码中如何排列这两个步骤…

coolshell文章阅读摘抄

coolshell文章阅读摘抄打好基础学好英语限制你的不是其它人&#xff0c;也不是环境&#xff0c;而是自己Java打好基础 程序语言&#xff1a;语言的原理&#xff0c;类库的实现&#xff0c;编程技术&#xff08;并发、异步等&#xff09;&#xff0c;编程范式&#xff0c;设计模…

数据库造神计划第六天---增删改查(CRUD)(2)

&#x1f525;个人主页&#xff1a;寻星探路 &#x1f3ac;作者简介&#xff1a;Java研发方向学习者 &#x1f4d6;个人专栏&#xff1a;《从青铜到王者&#xff0c;就差这讲数据结构&#xff01;&#xff01;&#xff01;》、 《JAVA&#xff08;SE&#xff09;----如此简单&a…

使用Rust实现服务配置/注册中心

Conreg 使用 Rust 实现的配置与注册中心&#xff0c;参考了 Nacos 的设计&#xff0c;简单易用&#xff0c;使用 Raft 保证集群节点数据一致性。 支持的平台&#xff1a; UbuntuCentOS其他常见的 Linux 发行版&#xff08;我们使用 musl 编译&#xff0c;理论上支持所有主流…

三色标记算法

在 JVM 并发垃圾收集&#xff08;GC&#xff09;中&#xff0c;三色标记算法是实现 “GC 线程与用户线程并行执行” 的关键技术&#xff0c;它解决了并发场景下 “如何准确标记存活对象” 的核心问题&#xff0c;是 CMS、G1 等现代收集器的底层基础。一、三色标记的核心&#x…

OpenStack 管理与基础操作学习笔记(一):角色、用户及项目管理实践

OpenStack实验 OpenStack命令 admin-openrc.sh 进入管理员视图查看当前 OpenStack 中的项目列表&#xff0c;验证是否已经登录成功切换用户 修改文件切换用户上传文件切换用户OpenStack 认证管理 实验介绍 通过 OpenStack Dashboard 和 OpenStack CLI 两种方式创建角色、用户、…

直接查找试卷且可以免费下载

有什么网站可以直接查找试卷且可以免费下载&#xff1f; SearXNG开源元搜索引擎 This website shows the SearXNG public instances searx一个可定制的搜索引擎 分享一个基于Blockstack的DApp-searx,一个可定制的搜索引擎。 1- 链接 官网地址&#xff1a;https://searx.worl…

【独立版】智创云享知识付费小程序 v5.0.23+小程序 搭建教程

介绍智创云享知识付费小程序v5.0.23 含PC、小程序、H5 、前端&#xff0c;系统独立版已修复已知bug问题。框架是一款基于ThinkPHP框架开发的虚拟资源知识付费小程序&#xff0c;为广大创业者、自媒体及培训机构提供知识付费、内容付费、资源变现等领域的行业解决方案&#xff1…

布尔运算-区间dp

面试题 08.14. 布尔运算 - 力扣&#xff08;LeetCode&#xff09; Solution 这题的思路比较直接&#xff0c;就是枚举最后一个进行计算的运算符&#xff0c;但是在实现过程中需要注意&#xff0c;定义范式f(l,r)表示l到r范围&#xff0c;l和r必须为数字&#xff0c;l1,r-1为运…

MyBatis-Plus 扩展全局方法

1.文件内容package com.ruoyi.business.mybatisplus.base;import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** 扩展的 Service 接口* 所有自定义 Service 接口都需要继承此接口…

13.Linux OpenSSH 服务管理

文章目录Linux OpenSSH 服务管理环境准备OpenSSH 服务介绍SSH 介绍SSH 建立连接的过程加密类型双向加密过程使用 ssh 访问远端CLIssh 工具演示ssh工具配置文件配置 ssh 密钥认证ssh 故障模拟故障模拟排故故障自定义 SSH 服务配置文件禁止 root 登录禁止密码登录只允许特定用户登…

速通ACM省铜第五天 赋源码(MEX Count)

目录 引言&#xff1a; MEX Count 题意分析 逻辑梳理 代码实现 结语&#xff1a; 引言&#xff1a; 本来&#xff0c;今天我是想着出俩题或三题题解的&#xff0c;但是在打第一题的时候就天塌了&#xff0c;导致今天就只搓了一道题&#xff0c;这题的难度在CF中为1300的水准&…

【数据结构与算法-Day 27】堆的应用:从堆排序到 Top K 问题,一文彻底搞定!

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…

企业即时通讯保障企业通讯安全,提升企业部门协作效率

在当今数字化转型的大潮中&#xff0c;企业即时通讯软件已从单纯的沟通工具&#xff0c;逐步演变为保障企业数据安全的核心基础设施。吱吱企业即时通讯软件通过“私有化部署全流程加密”的双重机制&#xff0c;为企业构建了一套集“通讯安全”与“部门协作”于一体的数字化解决…

《华为变革法:打造可持续进步的组织》读书笔记

推荐序一&#xff1a;变革是企业活下去的基础&#xff08;胡彦平&#xff09;华为前常务副总裁、变革指导委员会成员胡彦平在序言中强调&#xff0c;企业存续的核心命题是应对不确定性&#xff0c;而变革能力是破解这一命题的唯一答案。他以华为 30 余年的发展历程为例&#xf…

第二篇:排序算法的简单认识【数据结构入门】

排序算法的分类标准 时间复杂度分类 a. 简单排序算法&#xff1a;时间复杂度O(n)&#xff0c;冒泡排序、选择排序、插入排序&#xff1b; b. 高级排序算法&#xff1a;时间复杂度O(n logn)&#xff0c;快速排序、归并排序、堆排序&#xff1b; c. 线性排序算法&#xff1a;时间…

快速掌握Dify+Chrome MCP:打造网页操控AI助手

你是否曾经希望那些强大的开源大模型能更贴合你的专业领域&#xff0c;或者学会模仿你的行文风格&#xff1f;其实&#xff0c;实现这个目标的关键就在于“微调”。曾几何时&#xff0c;微调模型是大公司的专属游戏——动不动就需要几十张GPU和复杂的分布式训练技术。 而现在&…

单词记忆-轻松记忆10个实用英语单词(15)

1. repaint含义&#xff1a;重新油漆 读音标注&#xff1a;/ˌriːˈpeɪnt/ 例句&#xff1a;We need to repaint the walls after the repairs. 译文&#xff1a;修理完成后需要重新粉刷墙壁。 衍生含义&#xff1a;重新绘制&#xff08;图像场景&#xff09;&#xff1b;翻新…

visual studio快捷键

1.visual studio代码格式化快捷键 1.CtrlA&#xff08;全选&#xff09; 2.CtrlK 3.CtrlF2.多行注释 1.Ctrlk 2.Ctrlc2.多行取消注释 1.Ctrlk 2.Ctrlu

Django全栈班v1.04 Python基础语法 20250913 下午

练习&#xff1a;个人信息收集器 任务&#xff1a;创建一个个人信息收集和展示程序 要求&#xff1a; 收集用户的姓名&#xff0c;年龄&#xff0c;城市&#xff0c;爱好验证年龄输入&#xff0c;必须是正数格式化输出用户信息计算用户出生年份 name input("请输入姓名&a…