深入探索Java集合框架

在Java编程中,数据的组织和存储是核心部分。为了更有效地管理和操作这些数据,Java提供了一个强大且灵活的集合框架(Java Collection Framework,JCF)。这个框架不仅简化了数据结构的处理,还提供了高效的性能。在本文中,我们将深入探讨Java集合框架的组成、特性和用法。

目录

    • 一、Java集合框架的概述
    • 二、主要集合接口
      • 1. List接口
      • 2. Set接口
      • 3. Queue接口
      • 4. Deque接口
      • 5. Map接口
    • 三、迭代器
    • 四、工具类
    • 五、并发集合
      • 1. 阻塞式集合
      • 2. 非阻塞式集合
    • 六、总结

一、Java集合框架的概述

Java集合框架位于java.util包中,是Java编程语言的核心部分。它定义了几种类型的集合,包括列表(List)、集合(Set)、队列(Queue)、双端队列(Deque)以及映射(Map)。这些集合类型通过统一的接口和抽象类来实现,从而提供了对数据的一致视图。

二、主要集合接口

在Java集合框架中,接口是定义集合行为的关键。它们为不同类型的集合提供了通用的方法和规范。以下是主要集合接口的详细介绍:

1. List接口

List接口代表了一个有序集合,即元素在集合中的位置(索引)是有顺序的,并且允许存储重复的元素。List接口继承自Collection接口,并添加了一些特定于列表的操作,如获取指定位置的元素、替换元素、获取列表的子列表等。

以下是List接口的一些常用实现类:

  1. ArrayList
    ArrayListList接口的一个动态数组实现,它允许在运行时增长和缩小。ArrayList内部使用数组来存储元素,因此访问元素(get和set操作)的时间复杂度是O(1)。然而,插入和删除元素(特别是中间位置的元素)可能需要移动数组中的其他元素,因此时间复杂度可能是O(n)。ArrayList是非同步的,因此它不适合在多线程环境中使用,除非外部同步。

  2. LinkedList
    LinkedList是一个双向链表实现,它实现了ListDeque接口。LinkedList在列表的开头和结尾插入和删除元素时提供了常数时间性能,但在访问列表中的特定位置时则提供了线性时间性能。LinkedList还提供了额外的方法来操作列表的开头和结尾,这些方法继承自Deque接口。

  3. Vector
    Vector是一个类似于ArrayList的类,但它是同步的,这意味着它是线程安全的。Vector的每个方法都被synchronized修饰,因此在多线程环境中可以防止并发修改。然而,这种同步是有代价的,通常会导致性能下降。Vector还提供了一个可以增长其容量的机制,以便在添加大量元素时减少内存重新分配的次数。

  4. Stack
    StackVector的一个子类,它实现了标准的后进先出(LIFO)堆栈。Stack类提供了pushpoppeek等堆栈操作。尽管Stack继承自Vector并且因此是线程安全的,但通常不建议在新的代码中使用它,因为Deque接口及其实现(如ArrayDeque)提供了更完整、更灵活的堆栈和队列操作,并且通常具有更好的性能。

  5. CopyOnWriteArrayList
    CopyOnWriteArrayList是一个线程安全的List实现,它在修改时复制底层数组,从而实现了读写分离。这种设计使得读取操作可以在没有锁定的情况下进行,而写入操作则通过创建底层数组的新副本来实现。这使得CopyOnWriteArrayList非常适合读多写少的场景。然而,由于写入操作需要复制整个底层数组,因此当列表很大时,写入操作的性能可能会很差。

  6. AbstractListAbstractSequentialList
    这些类是用于创建自定义List实现的抽象基类。AbstractList提供了List接口的部分实现,而AbstractSequentialList则是一个更简单的实现,它只支持按顺序访问元素。开发人员可以扩展这些类来创建自己的列表实现,而无需从头开始实现整个接口。

2. Set接口

Set接口代表了一个无序集合,即元素在集合中的位置没有特定的顺序,并且集合中的元素是唯一的,不允许存储重复的元素。Set接口也继承自Collection接口,并添加了一些特定于集合的操作,如添加元素、删除元素、判断元素是否存在于集合中等。

ListQueue不同,Set中的元素是无序的,并且每个元素只能出现一次。Java标准库为Set接口提供了几种实现类,下面是一些常用的实现:

  1. HashSet
    HashSetSet接口的一个实现类,它使用哈希表(实际上是HashMap的一个实例)来存储元素。HashSet中的元素是无序的,并且不保证元素的迭代顺序。它允许null元素,并且由于其基于哈希表的实现,插入和查找操作通常是非常快的。

  2. LinkedHashSet
    LinkedHashSet也是一个Set接口的实现类,它维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到集合中的顺序(插入顺序)进行迭代。LinkedHashSet在迭代访问方面比HashSet更快,但需要更多的内存。

  3. TreeSet
    TreeSet是一个基于红黑树的NavigableSet实现。TreeSet中的元素是有序的,排序顺序可以是元素的自然顺序,或者通过构造函数传递的Comparator来决定。TreeSet不允许null元素,并且它实现了SortedSet接口,这意味着它提供了一些方法来处理排序集合,如first(), last(), headSet(), tailSet()等。

  4. EnumSet
    EnumSet是一个专为枚举类型设计的紧凑、高效的Set实现。在枚举类型的集合非常大或者需要特别快的性能时使用它是很合适的。EnumSet中的所有元素都必须是单个枚举类型的枚举值。

  5. CopyOnWriteArraySet
    CopyOnWriteArraySet是一个线程安全的Set实现,它通过使用内部的CopyOnWriteArrayList来实现。任何修改操作(如addremove)都会导致底层数组被复制,因此它适用于读操作远多于写操作的场景。

  6. ConcurrentSkipListSet
    ConcurrentSkipListSet是一个基于SkipList算法的无界并发NavigableSet实现。它的元素是有序的,排序顺序可以是元素的自然顺序,或者通过构造函数传递的Comparator来决定。这个类设计用于高并发的场景,其中多个线程可能同时访问集合,并且至少有一个线程会修改它。

这些实现类提供了丰富的功能集,以满足不同场景下的需求,从简单的元素存储到复杂的并发和排序操作。

3. Queue接口

Queue接口代表了一个队列,即一种先进先出(FIFO)的数据结构。队列中的元素按照它们被添加的顺序进行排列,并且只能从队列的头部移除元素,只能从队列的尾部添加元素。Queue接口也继承自Collection接口,并添加了一些特定于队列的操作,如添加元素到队列、从队列中移除元素、查看队列的头部和尾部元素等。

Java标准库提供了几种Queue接口的实现类,包括:

  1. LinkedListLinkedList类实现了Deque接口,而Deque接口扩展了Queue接口。因此,LinkedList可以用作队列,其中元素按照先进先出(FIFO)的顺序进行处理。它也可以用作栈,其中元素按照后进先出(LIFO)的顺序进行处理。
  2. PriorityQueuePriorityQueue类实现了一个基于优先级的无界队列。优先级队列的元素根据它们的自然顺序进行排序,或者根据传递给队列构造函数的Comparator进行排序,具体取决于所使用的构造方法。优先级队列不允许使用null元素。
  3. ArrayDequeArrayDeque是一个基于数组的双端队列,具有可预测的迭代顺序。该队列按 FIFO(先进先出)原则对元素进行排序。新元素插入到队列的末尾,队列检索操作在队列的开头进行。
  4. ConcurrentLinkedQueueConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它使用高效的非阻塞算法进行设计。
  5. LinkedBlockingDequeLinkedBlockingQueueArrayBlockingQueuePriorityBlockingQueueDelayQueueSynchronousQueue:这些都是java.util.concurrent包下的并发队列,用于多线程环境下的数据共享和传输。

需要注意的是,虽然LinkedList既实现了List接口也实现了Queue接口,但在使用时通常根据具体需求选择将其视为列表还是队列。

4. Deque接口

Deque(Double Ended Queue)接口代表了一个双端队列,即一种可以从两端添加和移除元素的队列。Deque接口继承自Queue接口,并添加了一些特定于双端队列的操作,如从队列的头部添加元素、从队列的尾部移除元素等。

以下是Deque接口的一些常用实现类:

  1. ArrayDeque
    ArrayDeque是一个基于动态数组的双端队列,它在内部使用一个循环数组来存储元素。这个类在大多数操作上(添加、删除和访问)都提供了常数时间的性能。ArrayDeque没有容量限制,它是根据需要动态扩展的。它是非同步的,不适用于多线程环境,除非进行外部同步。

  2. LinkedList
    LinkedList类也实现了Deque接口,除了可以作为双端队列使用外,它还是一个双向链表。这意味着它可以高效地从队列的两端添加和删除元素。与ArrayDeque相比,LinkedList在内存使用上更加灵活,因为它不需要连续的内存空间来存储元素。然而,LinkedList在中间位置进行插入和删除操作时性能更好,但如果主要用作队列或栈,ArrayDeque通常更快。

  3. ConcurrentLinkedDeque
    ConcurrentLinkedDeque是一个线程安全的双端队列,它基于链接节点的无界线程安全队列。此队列按照 FIFO(先进先出)原则对元素进行排序。新元素插入到队列的末尾,队列检索操作则是在队列的开头进行。然而,与LinkedList不同,ConcurrentLinkedDeque的设计使其支持高效的并发访问。它使用了类似于ConcurrentLinkedQueue的高级并发控制技术。

  4. BlockingDeque 接口及其实现:
    BlockingDequeDequeBlockingQueue接口的结合,它定义了一个线程安全的双端队列,该队列在尝试检索或删除元素时会阻塞,直到队列非空或可以插入元素为止。Java标准库没有直接提供BlockingDeque的具体实现类,但你可以通过java.util.concurrent包中的其他类(如LinkedBlockingDeque)来找到这样的功能。

    • LinkedBlockingDeque
      LinkedBlockingDeque是一个基于链接节点的可选容量的阻塞双端队列。此队列按 FIFO(先进先出)排序元素。它可以在队列的两端添加和删除元素,并提供了可选的容量限制。当队列为空时,获取元素的线程将会阻塞,直到有其他线程插入新的元素;当队列满时,尝试添加元素的线程将会阻塞,直到有其他线程删除一些元素腾出空间。这使得LinkedBlockingDeque非常适合在生产者-消费者场景中使用。
import java.util.ArrayDeque;  
import java.util.Deque;  public class DequeExample {  public static void main(String[] args) {  Deque<String> deque = new ArrayDeque<>();  deque.push("A"); // 在队列头部插入元素  deque.push("B");  deque.offer("C"); // 在队列尾部插入元素  System.out.println("Initial deque: " + deque);  String head = deque.pop(); // 移除并返回队列头部的元素  System.out.println("Removed from head: " + head);  System.out.println("Deque after pop: " + deque);  String tail = deque.pollLast(); // 移除并返回队列尾部的元素  System.out.println("Removed from tail: " + tail);  System.out.println("Deque after pollLast: " + deque);  }  
}

5. Map接口

Map接口代表了一个键值对集合,即一种存储键值对数据的数据结构。Map接口中的每个元素都包含一个键和一个与之相关联的值。键在Map中是唯一的,不允许存储重复的键。Map接口提供了一些特定于键值对的操作,如添加键值对、根据键获取值、删除键值对等。

以下是Map接口的一些常用实现类:

  1. HashMap
    HashMapMap接口的一个基于哈希表的实现,它允许null键和null值。HashMap提供了常数时间的性能来进行基本的操作(getput),假设哈希函数将元素适当地分布在桶中。然而,这并不意味着HashMap的所有操作都是O(1)的,特别是在哈希表需要进行重哈希(rehashing)以处理哈希冲突时。

  2. LinkedHashMap
    LinkedHashMapHashMap的一个子类,它维护了一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将键-值对插入到映射中的顺序(插入顺序)或访问顺序进行迭代。因此,LinkedHashMap在迭代访问方面比HashMap更快,但需要更多的内存。

  3. TreeMap
    TreeMap是一个基于红黑树的NavigableMap实现。TreeMap中的键是有序的,排序顺序可以是键的自然顺序,或者通过构造函数传递的Comparator来决定。TreeMap不允许null键(像HashMap一样允许一个null键)。TreeMap提供了高效的键排序、范围查询和其他导航方法。

  4. Hashtable
    HashtableMap接口的一个遗留实现,它的所有公共方法都是同步的,因此它是线程安全的。但是,与HashMap相比,Hashtable的性能通常要低得多,因为同步操作会导致性能开销。Hashtable不允许null键和null值。在现代Java应用中,通常建议使用ConcurrentHashMap来处理需要线程安全的映射。

  5. ConcurrentHashMap
    ConcurrentHashMap是一个线程安全的HashMap实现,它使用了分段锁或其他并发控制技术(在Java 8及更高版本中,它使用了一种称为CAS和synchronized的更精细的并发控制策略)来实现高并发性能。ConcurrentHashMap中的读取操作可以在没有锁定的情况下进行,而写入操作则通过锁定部分映射来实现。这使得ConcurrentHashMap非常适合于读多写少的并发场景。

  6. IdentityHashMap
    IdentityHashMap是一个特殊的Map实现,它使用引用相等性(==)而不是对象相等性(equals()方法)来比较键。这意味着即使两个键在内容上相等(即它们的equals()方法返回true),但如果它们不是同一个对象(即它们的引用不同),那么它们在IdentityHashMap中也被视为不同的键。这种映射在需要基于对象身份进行映射的罕见情况下非常有用。

  7. EnumMap
    EnumMap是一个专为枚举类型设计的紧凑、高效的Map实现。在枚举类型的映射非常大或者需要特别快的性能时使用它是很合适的。EnumMap中的所有键都必须是单个枚举类型的枚举值。它在内部使用一个位向量或数组来表示映射,这使得它在存储和访问方面都非常高效。但是,它只能用于枚举键的映射,并且不允许使用null键。

三、迭代器

迭代器(Iterator)是Java集合框架中的一个关键概念。它提供了一种方法来访问集合中的每个元素,而无需暴露该集合的底层表示。通过Iterator接口,我们可以顺序地访问集合中的元素,并执行添加、删除等操作。

除了普通的Iterator外,Java集合框架还提供了ListIterator,它专为List接口设计,允许程序员在遍历列表时添加和替换元素,以及双向遍历列表。

四、工具类

Java集合框架还提供了两个实用的工具类:Arrays和Collections。这些类包含了许多静态方法,用于操作数组和集合。例如,我们可以使用Arrays类的sort()方法对数组进行排序,或使用Collections类的shuffle()方法随机打乱集合中的元素顺序。

五、并发集合

在Java中,当需要在多线程环境下操作集合时,普通的集合类(如ArrayList、HashSet等)可能会因为并发修改导致数据不一致的问题。为了解决这个问题,Java集合框架提供了一系列支持并发操作的集合类,这些集合类被称为并发集合。

并发集合主要分为两类:阻塞式集合和非阻塞式集合。

1. 阻塞式集合

阻塞式集合是指当集合已满或为空时,对集合进行添加或移除操作的线程会被阻塞,直到操作可以成功执行为止。典型的阻塞式集合实现类有:

  • LinkedBlockingDeque:一个基于链表的双端阻塞队列。它支持在队列的两端进行插入和移除操作,当队列已满时,添加操作的线程会被阻塞;当队列为空时,移除操作的线程会被阻塞。
  • LinkedTransferQueue:一个基于链表的阻塞队列,它支持在生产者和消费者之间进行数据的直接传递。如果消费者线程正在等待接收数据,而生产者线程正好生产了数据,那么生产者线程可以直接将数据传递给消费者线程,而不需要将数据先添加到队列中。
  • PriorityBlockingQueue:一个支持优先级排序的阻塞队列。队列中的元素按照优先级进行排序,优先级最高的元素总是位于队列的头部。当队列已满时,添加操作的线程会被阻塞;当队列为空时,移除操作的线程会被阻塞。
  • DelayQueue:一个支持延迟获取的阻塞队列。队列中的元素只有在达到指定的延迟时间后才能被获取。如果尝试获取未达到延迟时间的元素,获取操作的线程会被阻塞。

2. 非阻塞式集合

非阻塞式集合是指在进行添加或移除操作时,如果操作不能立即执行,那么会立即返回一个结果(通常是null或抛出异常),而不会阻塞调用线程。典型的非阻塞式集合实现类有:

  • ConcurrentHashMap:一个支持并发操作的哈希表。它允许多个线程同时访问和修改哈希表中的数据,而不会引起竞争条件。ConcurrentHashMap内部使用分段锁技术来实现并发控制,每个段(Segment)都有自己的锁,不同线程可以并发地访问不同段中的数据。
  • ConcurrentSkipListMap:一个支持并发操作的跳表实现。跳表是一种可以在对数期望时间内完成搜索、插入、删除等操作的数据结构。ConcurrentSkipListMap内部使用无锁算法来实现并发控制,允许多个线程同时访问和修改跳表中的数据而不会引起竞争条件。与ConcurrentHashMap相比,ConcurrentSkipListMap在需要保持元素有序的场景下更为适用。
  • CopyOnWriteArrayListCopyOnWriteArraySet:这两个类分别是支持并发操作的动态数组和集合实现。它们采用写时复制(Copy-On-Write)的策略来实现并发控制。当需要修改集合中的数据时,会先将数据复制一份,然后在复制品上进行修改,修改完成后再将指针指向新的复制品。这样可以保证在修改过程中不会阻塞读取操作的线程,因为读取操作仍然可以访问旧的集合数据。但是需要注意的是,由于写时复制需要复制整个集合数据,因此在大规模数据集合的场景下可能会导致较高的内存开销和性能损耗。

总的来说,Java的并发集合为多线程环境下的数据操作提供了强大的支持,使得开发人员可以更加容易地编写出高效、安全、可靠的并发程序。在选择具体的并发集合实现类时,需要根据具体的应用场景和需求来进行选择。

六、总结

Java集合框架是一个强大且灵活的工具,它简化了数据结构的处理,提高了代码的可重用性和可维护性。通过掌握Java集合框架的接口、实现类和工具类,我们可以更加高效地组织和操作数据,从而提升Java应用程序的性能和质量。

希能帮助您更深入地理解Java集合框架的组成和用法。在实际编程中,请根据您的需求选择合适的集合类型和实现类,并充分利用Java集合框架提供的工具和特性来优化您的代码。

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

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

相关文章

Opencv基本操作 (上)

目录 图像基本操作 阈值与平滑处理 图像阈值 图像平滑处理 图像形态学操作 图像梯度计算 Sobel 算子 Canny 边缘检测 图像金字塔与轮廓检测 图像轮廓 接口定义 轮廓绘制 轮廓特征与相似 模板匹配 傅里叶变换 傅里叶变换的作用 滤波 图像基本操作 读取图像&…

GDPU 算法分析与设计 天码行空 1

实验1 排序算法的效率分析 一、【实验目的】 &#xff08;1&#xff09;复习排序算法的实现过程&#xff1b; &#xff08;2&#xff09;设计平均与最坏情况下时间复杂度的数据环境并理解相关含义&#xff1b; &#xff08;3&#xff09;初步了解算法时间复杂度的分析方法。…

【Maven】Maven 基础教程(二):Maven 的使用

《Maven 基础教程》系列&#xff0c;包含以下 2 篇文章&#xff1a; Maven 基础教程&#xff08;一&#xff09;&#xff1a;基础介绍、开发环境配置Maven 基础教程&#xff08;二&#xff09;&#xff1a;Maven 的使用 &#x1f60a; 如果您觉得这篇文章有用 ✔️ 的话&#…

Qt中关于信号与槽函数的思考

信号与槽函数的思考 以pushbutton控件为例&#xff0c;在主界面上放置一个pushbutton控件&#xff0c;点击右键选择关联槽函数&#xff0c;关联一个click函数&#xff0c;如下图所示&#xff1a; 在该函数中&#xff0c;实现了一个点击pushbutton按钮后&#xff0c;弹出一个窗…

nginx使用详解--反向代理

什么是反向代理&#xff1f; 正向代理&#xff1a; 一般的访问流程是客户端直接向目标服务器发送请求并获取内容&#xff0c;使用正向代理后&#xff0c;客户端改为向代理服务器发送请求&#xff0c;并指定目标服务器&#xff08;原始服务器&#xff09;&#xff0c;然后由代理…

在极狐GitLab 配置 SSL/https

本文作者 徐晓伟 说明 极狐GitLab https 使用的是 nginx 实现的本文使用的域名是IP 192.168.80.14&#xff08;原因&#xff1a;如果使用域名&#xff0c;必须拥有这个域名的所有权&#xff0c;并增加解析才可以&#xff0c;要不然在 Docker 容器中&#xff0c;无法使用域名检…

go并发模式之----使用时顺序模式

常见模式之二&#xff1a;使用时顺序模式 定义 顾名思义&#xff0c;起初goroutine不管是怎么个先后顺序&#xff0c;等到要使用的时候&#xff0c;需要按照一定的顺序来&#xff0c;也被称为未来使用模式 使用场景 每个goroutine函数都比较独立&#xff0c;不可通过参数循环…

DOM 获取父子节点

DOM 是以树状结构排列的&#xff0c;所以父子关系是相对的&#xff0c;当li为我们的目标节点的时候&#xff0c;ul为其父节点&#xff0c;其他li为它的兄弟节点&#xff0c;li里面包含的标签为子节点&#xff0c;以此类推。 那我们如何找父节点&#xff1f; 元素.parentNode&am…

libigl 网格质量矩阵

文章目录 一、简介二、应用三、实现效果参考资料一、简介 在 libigl 中,igl::massmatrix 是一个用于计算给定三角网格的质量矩阵的函数。质量矩阵在有限元分析和其他模拟技术中非常有用,它通常用于描述网格中各个节点的质量或者用于计算模拟过程中的惯性效应。 igl::massmatr…

分布式系统如何做数据对账?

前言 在分布式系统中&#xff0c;虽然我们会使用各种分布式事务的方案&#xff0c;来保证各个系统之间的一致性。但是&#xff0c;很多时候往往事与愿违。 尤其是现在很多公司都采用最终一致性的方案&#xff0c;而所谓最终一致性&#xff0c;无论是本地消息表、事务消息、还…

蓝桥杯:数组分割(Java)

目录 问题描述输入格式输出格式代码实现 问题描述 小蓝有一个长度为N的数组A[A0,A1,… AN-1]。现在小蓝想要从A对应的数组下标所构成的集合Ⅰ0,1,2,…,N -1中找出一个子集R1&#xff0c;那么R1在Ⅰ中的补集为R2。记S1∈∑Ar&#xff0c;S2∈∑Ar&#xff0c;我们要求S1和S2均为…

node 之 npm

1.什么是包 node.js中的第三方模块又叫做包 就像电脑和计算机指的是相同的东西&#xff0c;第三方模块和包指的是同一个概念&#xff0c;只不过叫法不同 2.包的来源 不同于 Node.js 中的内置模块与自定义模块&#xff0c;包是由第三方个人或团队开发出来的&#xff0c;免费供所…

【计算机网络——应用层】http协议

文章目录 1. http协议1.1 http协议简介1.2 url组成1.3 urlencode与urldecode 2. http协议的格式2.1 http协议的格式2.2 一些细节问题 3. http的方法、状态码和常见响应报头3.1 http请求方法3.2 http状态码3.3 http常见的响应报头属性 4. 一个非常简单的http协议服务端5. http长…

【X806开发板试用】文章一 ubuntu开发环境搭建

一、环境配置 官方链接&#xff1a; 环境配置 1.安装必要的库和软件 sudo apt-get install build-essential gcc g make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-b…

pix2pix-zero

pix2pix-zero&#xff1a;零样本图像到图像转换 论文介绍 Zero-shot Image-to-Image Translation 关注微信公众号: DeepGoAI 项目地址&#xff1a;https://github.com/pix2pixzero/pix2pix-zero 论文地址&#xff1a;https://arxiv.org/abs/2302.03027 本文介绍了一种名为…

Golang 函数中 defer 和 return 的调用顺序

先来看一段代码&#xff1a; package mainimport "fmt"func f() (ret int) {defer func() {ret}()return 1 } func main() {fmt.Println(f()) }上面这段代码的输出是2&#xff0c;不是1 原因在于&#xff1a; 1&#xff09;ret 是在执行 return 1 语句后发生的 2&…

基于SpringBoot多模块项目引入其他模块时@Autowired无法注入

基于SpringBoot多模块项目引入其他模块时Autowired无法注入 一、问题描述1、解决方案 一、问题描述 启动Spring Boot项目时报 Could not autowire. No beans of ‘xxxxxxxx’ type found. 没有找到bean的实例&#xff0c;即spring没有实例化对象&#xff0c;也就无法根据配置文…

【LeetCode-中等】209.长度最小的子数组-双指针/滑动窗口

力扣题目链接 1. 暴力解法 这道题的暴力解法是两层嵌套for循环&#xff0c;第一层循环从 i 0 开始遍历至数组末尾&#xff0c;第二层循环从 j i 开始遍历至找到总和大于等于 target 的连续子数组&#xff0c;并将该连续子数组的长度与之前找到的子数组长度相比较&#xff0…

传输层两大战将TCP、UDP的定位

传输层 定义一些传输数据的协议和端口&#xff0c;传输协议同时进行流量控制&#xff0c;根据接收方的数据吞入熟读&#xff0c;规定适当的发送速率&#xff0c;解决传输效率及能力问题 什么是TCP TCP/IP即传输控制/网络协议&#xff0c;是面向连接的协议&#xff0c;发送数…

什么是IP公网?

IP公网是指互联网上可以公开访问的IP地址。它是经过互联网服务提供商&#xff08;ISP&#xff09;向用户提供的公共网络IP地址。与之相对的是内网IP地址&#xff0c;内网IP地址一般是由路由器或交换机分配给连接在局域网中的设备使用。 IP公网的作用非常广泛&#xff0c;可以应…