Java集合篇

news/2024/4/29 11:10:33/文章来源:https://blog.csdn.net/qq_45832461/article/details/132013494

前言:笔者参考了JavaGuide、三分恶等博主的八股文,结合Chat老师和自己的理解,整理了一篇关于Java集合的八股文。希望对各位读者有所帮助~~

引言

常见集合有哪些?

Java集合相关类和接口都在java.util包中,按照其存储结构集合可以分为两大类:单列集合 Collection 和双列集合 Map。Collection派生出了三个子接口:List、Set、Queue,因此Java集合大致也可分成List、Set、Queue、Map四种接口体系。

单列集合Collection

在这里插入图片描述

  • List:元素有序、可重复,这里所谓的有序意思是:元素的存入顺序和取出顺序一致。例如,存储元素的顺序是 11、22、33,那么我们从 List 中取出这些元素的时候也会按照 11、22、33 这个顺序。List 接口的常用实现类有:
    • ArrayList:底层数据结构是数组,线程不安全;
    • LinkedList:底层数据结构是链表,线程不安全;
  • Set:元素不可重复,不能通过整数索引来访问,并且元素无序。所谓无序也就是元素的存入顺序和取出顺序不一致。其常用实现类有:
    • HashSet:底层基于 HashMap 实现,采用 HashMap 来保存元素;
    • LinkedHashSetLinkedHashSetHashSet 的子类,并且其底层是通过 LinkedHashMap 来实现的;
  • Queue:先进先出的队列。其常用实现类有:PriorityQueue

双列集合Map

Map:元素是成对存在的。每个元素由键(key)与值(value)两部分组成,通过键可以找对所对应的值。显然这个双列集合解决了数组无法存储映射关系的痛点。另外,需要注意的是,Map 不能包含重复的键,值可以重复;并且每个键只能对应一个值。

在这里插入图片描述

需要注意的是,这些容器都只能存储对象引用类型,也就是说当我们需要装载的数据是诸如 intfloat 等基本数据类型的时候,必须把它们转换成对应的包装类。

线程安全的集合有哪些?线程不安全的呢?

线程安全的:

  • Hashtable:比HashMap多了个线程安全。
  • ConcurrentHashMap:是一种高效但是线程安全的集合。
  • Vector:比Arraylist多了个同步化机制。
  • Stack:栈,也是线程安全的,继承于Vector。

线程不安全的:

  • HashMap
  • ArrayList
  • LinkedList
  • HashSet
  • TreeSet
  • TreeMap

List

ArrayList和LinkedList有什么区别?

  • ArrayList和LinkedList都是线程不安全的;
  • ArrayList 的实现是基于数组,LinkedList 的实现是基于双向链表;
  • ArrayList 采用数组存储,所以插入和删除元素受元素位置的影响;LinkedList采用链表存储,所以插入和删除元素不受元素位置的影响;
  • ArrayList 支持随机访问,而 LinkedList 不支持。ArrayList 可以根据下标以 O ( 1 ) O(1) O(1)时间复杂度对元素进行随机访问,而 LinkedList 的每一个元素都依靠地址指针和它后一个元素连接在一起,查找某个元素的时间复杂度是 O ( n ) O(n) O(n)
  • LinkedList 比 ArrayList 更占内存。因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素;

讲讲ArrayList的扩容机制?

ArrayList是基于数组的集合,数组的容量是在定义的时候确定的,如果数组满了再插入,就会数组溢出。所以在插入时候,会先检查是否需要扩容,如果当前容量+1超过数组长度,就会进行扩容。

扩容发生在啥时候?那肯定是我们往数组中新加入一个元素但是发现数组满了的时候。没错,我们去 add 方法中看看 ArrayList 是怎么做扩容的:

在这里插入图片描述

ensureExplicitCapacity 判断是否需要进行扩容,很显然,grow 方法是扩容的关键:
在这里插入图片描述

别的都不用看了,看上面图中的黄色框框就知道 ArrayList 是怎么扩容的了:扩容后的数组长度 = 当前数组长度 + 当前数组长度 / 2(也就是【1.5 倍】)。最后使用 Arrays.copyOf 方法直接把原数组中的数组 copy 过来,需要注意的是,Arrays.copyOf 方法会创建一个新数组然后再进行拷贝。

扩容操作需要调用 Arrays.copyOf()(底层 System.arraycopy())需要把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数。

举个栗子:
在这里插入图片描述

Arraylist 扩容的数组长度为什么是原数组长度的 1.5 倍?

这种扩容方式能够有效地平衡内存空间的使用和程序性能之间的关系。如果每次扩容时都将数组长度翻倍,可能会导致数组长度过大,浪费内存空间,而如果每次扩容时只增加一个固定的长度,可能会导致频繁扩容,影响程序性能。因此,1.5倍左右的扩容因子是一个比较理想的选择。

ArrayList怎么序列化的知道吗? 为什么用transient修饰数组?

ArrayList的序列化不太一样,它使用 transient 修饰存储元素的 elementData 的数组, transient 关键字的作用是让被修饰的成员属性不被序列化。

为什么最ArrayList不直接序列化元素数组呢?

出于效率的考虑,数组可能长度100,但实际只用了50,剩下的50不用其实不用序列化,这样可以提高序列化和反序列化的效率,还可以节省内存空间。

那ArrayList怎么序列化呢?

ArrayList通过两个方法readObjectwriteObject自定义序列化和反序列化策略,实际直接使用两个流ObjectOutputStreamObjectInputStream来进行序列化和反序列化。
在这里插入图片描述

什么是CopyOnWriteArrayList?

CopyOnWriteArrayList就是线程安全版本的ArrayList。它的名字叫 CopyOnWrite ——写时复制,已经明示了它的原理。

CopyOnWriteArrayList采用了一种读写分离的并发策略。CopyOnWriteArrayList容器允许并发读,读操作是无锁的,性能较高。至于写操作,比如向容器中添加一个元素,则首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器。

在这里插入图片描述

ArrayList 与Vector区别?

  • 实现:都实现了List接口,底层都使用 Object[]数组存储。
  • 线程安全: Vector使用了Synchronized 来实现线程同步,是线程安全的,而 ArrayList是非线程安全的。
  • 扩容: Vector 每次扩容请求其大小的 2 倍(也可以通过构造函数设置增长的容量),而 ArrayList 是 1.5 倍。
  • 性能: ArrayList在性能方面要优于Vector。

Map

HashMap 有什么特点?

HashMap 基于哈希表的 Map 接口实现,是以 key-value 存储形式存在,主要用来存放键值对。

  • HashMap 的实现不是同步的,这意味着它不是线程安全的;
  • key 是唯一不重复的,底层的哈希表结构,依赖 hashCode 方法和 equals 方法保证键的唯一;
  • key、value 都可以为null,但是 key 位置只能是一个null;
  • HashMap 中的映射不是有序的,即存取是无序的;
  • key 要存储的是自定义对象,需要重写 hashCode 和 equals 方法,防止出现地址不同内容相同的 key;
  • JDK1.8 之前 HashMap 由 数组+链表 组成
    • 数组是 HashMap 的主体;
    • 链表则是为了解决哈希冲突而存在的(拉链法解决冲突),拉链法就是头插法,两个对象调用的 hashCode 方法计算的哈希码值(键的哈希)一致导致计算的数组索引值相同;
  • JDK1.8 以后 HashMap 由 数组+链表 +红黑树数据结构组成
    • 解决哈希冲突时有了较大的变化;
    • 当链表长度超过阈值(或者红黑树的边界值,默认为 8)并且当前数组的长度大于等于 64 时,此索引位置上的所有数据改为红黑树存储;
    • 即使哈希函数取得再好,也很难达到元素百分百均匀分布。当 HashMap 中有大量的元素都存放到同一个桶中时,就相当于一个长的单链表,假如单链表有 n 个元素,遍历的时间复杂度是 O ( n ) O(n) O(n),所以 JDK1.8 中引入了 红黑树(查找时间复杂度为 O ( l o g n ) O(logn) O(logn))来优化这个问题,使得查找效率更高

HashMap的底层数据结构是什么?

在JDK1.7 中,由“数组+链表”组成:数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。
在JDK1.8 中,由“数组+链表+红黑树”组成:当链表过长,则会严重影响 HashMap 的性能,红黑树搜索时间复杂度是 O ( l o g n ) O(logn) O(logn),而链表是糟糕的 O ( n ) O(n) O(n)。因此,JDK1.8 对数据结构做了进一步的优化,引入了红黑树。链表和红黑树在达到一定条件会进行转换。

数据结构示意图如下:
在这里插入图片描述

其中,桶数组是用来存储数据元素,链表是用来解决冲突,红黑树是为了提高查询的效率。

  • 数据元素通过映射关系,也就是散列函数,映射到桶数组对应索引的位置;
  • 如果发生冲突,从冲突的位置拉一个链表,插入冲突的元素;
  • 如果链表长度>8&数组大小>=64,链表转为红黑树;
  • 如果红黑树节点个数<6 ,转为链表;

了解红黑树嘛?

红黑树本质上是一种二叉查找树,为了保持平衡,它又在二叉查找树的基础上增加了一些规则:

  1. 每个节点要么是红色,要么是黑色;
  2. 根节点永远是黑色的;
  3. 所有的叶子节点都是黑色的(注意这里说叶子节点其实是图中的 NULL 节 点);
  4. 每个红色节点的两个子节点一定都是黑色;
  5. 从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点;

在这里插入图片描述

为什么HashMap不使用二叉树/平衡树/B树、B+树呢?

之所以不用二叉树:

红黑树是一种不严格的平衡二叉树,插入、删除、查找的最坏时间复杂度都为 O(logn),避免了二叉树最坏情况下的O(n)时间复杂度。

之所以不用平衡二叉树:

平衡二叉树是比红黑树更严格的平衡树,是一种高度平衡的二叉树,查询效率高。但是为了维持这种高度的平衡,需要旋转的次数更多,每次插入、删除都要做调整,就比较复杂、耗时,也就是说平衡二叉树保持平衡的效率更低。因此,红黑树的查询性能略微逊色于二叉平衡树, 但是红黑树在插入和删除上优于二叉平衡树。总体来说,红黑树的插入、删除、查找各种操作性能都比较稳定。

之所以不用B树、B+树:

  • B+树在数据库中被应用的原因就是B+树比B树更加“矮胖”,B+树的非叶子结点不存储数据,所以每个结点能存储的关键字更多。所以B+树更能应对大量数据的情况。如果用B+树的话,在数据量不是很多的情况下,数据都会“挤在”一个结点里面。这个时候遍历效率就退化成了链表;
  • B和B+树主要用于数据存储在磁盘上的场景,比如数据库索引就是用B+树实现的。这两种数据结构的特点就是树比较矮胖,每个结点存放一个磁盘大小的数据,这样一次可以把一个磁盘的数据读入内存,减少磁盘转动的耗时,提高效率。而红黑树多用于内存中排序,也就是内部排序。

红黑树怎么保持平衡的知道吗?

红黑树有两种方式保持平衡:旋转(左旋和右旋)和染色。
在这里插入图片描述

HashMap的put流程知道吗?

流程图如下:
在这里插入图片描述

  1. 首先判断数组是否为空,为空则调用 resize 进行初始化;
  2. 根据 key 的值计算 hash 值,找到该元素在数组中存储的下标;
  3. 如果没有哈希冲突直接放在对应的数组下标里;
  4. 如果冲突了,且 key 已经存在,就覆盖掉 value;
  5. 如果冲突后,发现该节点是红黑树,就将这个节点挂在树上;
  6. 如果冲突后是链表,判断该链表是否大于 8 ,如果大于 8 并且数组长度小于 64,就进行扩容;如果链表节点大于 8 并且数组长度大于 64,则将这个结构转换为红黑树;否则,链表插入键值对,若 key 存在,就覆盖掉 value。

HashMap怎么查找元素的呢?

先看流程图:
在这里插入图片描述

HashMap的查找流程:

  1. 使用扰动函数,获取新的哈希值;
  2. 计算数组下标,获取节点;
  3. 当前节点和key匹配,直接返回;
  4. 否则,当前节点是否为树节点,查找红黑树;
  5. 否则,遍历链表查找。

HashMap的哈希/扰动函数是怎么设计的?

HashMap的哈希函数是先拿到 key 的hashcode,是一个32位的int类型的数值,然后让hashcode的高16位和低16位进行异或操作。

static final int hash(Object key) {int h;// key的hashCode和key的hashCode右移16位做异或运算return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

这么设计是为了降低哈希碰撞的概率。

你还知道哪些哈希函数的构造方法呢?

HashMap里哈希构造函数的方法叫除留取余法 :H(key) = key%p(p<=N),关键字除以一个不大于哈希表长度的正整数p,所得余数为地址,当然HashMap里进行了优化改造,效率更高,散列也更均衡。

除此之外,还有这几种常见的哈希函数构造方法:

  • 直接定址法:直接根据 key 来映射到对应的数组位置,例如1232放到下标1232的位置。
  • 数字分析法:取 key 的某些数字(例如十位和百位)作为映射的位置。
  • 平方取中法:取 key 平方的中间几位作为映射的位置。
  • 折叠法:将 key 分割成位数相同的几段,然后把它们的叠加和作为映射的位置。

在这里插入图片描述

解决哈希冲突有哪些方法呢?

解决Hash冲突方法有:开放寻址法、再哈希法、链地址法(拉链法)、建立公共溢出区。HashMap中采用的是链地址法 。

  • 开放寻址法:开放寻址法也称为再散列法,基本思想就是如果p = H(key)出现冲突时,则以p为基础,再次hash,p1 = H(p),直到找到一个不冲突的哈希地址。 因此开放定址法所需要的hash表的长度要大于等于所需要存放的元素,而且因为存在再次hash,所以只能在删除的节点上做标记,而不能真正删除节点。
  • 再哈希法:再哈希法(双重散列,多重散列),提供多个不同的hash函数,当R1 = H1(key1)发生冲突时,再计算R2 =H2(key1),直到没有冲突为止。 这样做虽然不易产生堆集,但增加了计算的时间。
  • 链地址法(拉链法):在冲突的位置拉一个链表,把冲突的元素放进去。链地址法适用于经常进行插入和删除的情况。
  • 建立公共溢出区:再建一个数组,把冲突的元素放进去。

为什么HashMap链表转红黑树的阈值为8呢?

源码的注释也给出了答案:
在这里插入图片描述

这和统计学有关。理想情况下,使用随机哈希码,链表里的节点符合泊松分布,出现节点个数的概率是递减的,节点个数为8的情况,发生概率仅为0.00000006 。至于红黑树转回链表的阈值为什么是6,而不是8呢?这是因为如果这个阈值也设置成8,那么假如发生碰撞,节点增减刚好在8附近,则会发生链表和红黑树的不断转换,导致资源浪费。

**扩容在什么时候呢 **

为了减少哈希冲突发生的概率,当当前HashMap的元素个数达到一个临界值的时候,就会触发扩容,把所有元素rehash之后再放在扩容后的容器中,这是一个相当耗时的操作。

临界值threshold就是由加载因子和当前容器的容量大小来确定的,假如采用默认的构造方法:

临界值(threshold )= 默认容量(DEFAULT_INITIAL_CAPACITY) * 默认扩 容因子(DEFAULT_LOAD_FACTOR)
在这里插入图片描述

那就是大于 16 × 0.75 = 12 16\times 0.75=12 16×0.75=12时,就会触发扩容操作。

为什么选择了0.75作为HashMap的默认加载因子呢?

简单来说,这是对空间成本和时间成本平衡的考虑。

在HashMap中有这样一段注释:
在这里插入图片描述

我们都知道,HashMap的散列构造方式是Hash取余,负载因子决定元素个数达到多少时候扩容。

假如我们设的比较大,元素比较多,空位比较少的时候才扩容,那么发生哈希冲突的概率就增加了,查找的时间成本就增加了。

假设我们设的比较小的话,元素比较少,空位比较多的时候就扩容了,发生哈希碰撞的 概率就降低了,查找时间成本降低,但是就需要更多的空间去存储元素,空间成本就增加了。

总结,主要是在时间成本和空间成本上做的折衷:

  • 如果负载因子太高,确实可以减少空间开销,但会增加查找复杂度(哈希冲突的概率增加,链表上的元素也就越多,查询的效率也就越低);
  • 如果负载因子太低,就会频繁触发 resize 导致 rehash 操作;

具体到底为什么精确到 0.75 这个数值,可以看这篇文章的解释:博客 。

HashMap和Hashtable的区别?

  1. 线程安全:Hashtable方法sychonized修饰,线程安全;
  2. 效率方面:由于Hashtable方法被sychonized修饰,效率比HashMap低;
  3. 底层数据结构:HashMap jdk8当链表长度>8并且数组长度>=64链表会转红黑树,Hashtable没有这样机制;
  4. 初始容量: 默认初始量:Hashtable为11,HashMap为16;若指定初始量: Hashtable用指定的值,HashMap会扩充为2的幂次方大小;
  5. 扩容:Hashtable容量变为原来2n+1倍,HashMap变为2倍;
  6. 对Null key与Null value支持: HashMap支持一个Null key多个Null value,Hashtable不支持Null key 和 Null value,否则报错空指针异常;

HashMap jdk8与jdk7区别?

  • 数据结构:1.7中是数组+链表,1.8中是数组+链表 或 数组 + 链表 + 红黑树。原因:发生哈希冲突,元素会存入链表,链表过长转为红黑树,将时间复杂度由 O(n) 降为 O(logn)。
  • 链表插入方式:1.7是头插法,1.8是尾插法。原因:因为1.7头插法扩容时,头插法会使链表发生反转,多线程环境下会产生环。
  • 扩容rehash:1.7 需要对原数组中的元素进行重新 hash 定位在新数 组的位置,1.8不需要重新通过哈希函数计算位置,新的位置不变或索引 + 旧的数组容量大小。原因:提高扩容的效率,更快地扩容。
  • 扩容时机:1.7是先判断是否需要扩容然后再插入,1.8是先进行插入,插入完成再判断是否需要扩容;
  • 散列函数:1.7 做了四次移位和四次异或,jdk1.8只做一次。原因:做四次的话,边际效用也不大,改为一次,提升效率。

HashMap 是线程安全的吗? 多线程下会有什么问题?

HashMap不是线程安全的,可能会发生这些问题:

  1. 多线程下扩容死循环。JDK1.7 中的 HashMap 使用头插法插入元素,在多线程的环境下,扩容的时候有可能导致环形链表的出现,形成死循环。因此,JDK1.8 使用尾插法插入元素,在扩容时会保持链表元素原本的顺序,不会出现环形链表的问题。
  2. 多线程的 put 可能导致元素的丢失。多线程同时执行 put 操作,如果计算出来的索引位置是相同的,那会造成前一个 key 被后一个 key 覆盖,从而导致元素的丢失。此问题在 JDK 1.7 和 JDK 1.8 中都存在。
  3. put 和 get 并发时,可能导致 get 为 null。线程 1 执行 put 时,因为元素个数超出 threshold 而导致 rehash,线程 2 此时执行 get,有可能导致这个问题。这个问题在 JDK 1.7 和 JDK 1.8 中都存在。

有什么办法能解决HashMap线程不安全的问题呢?

Java 中有 HashTable、Collections.synchronizedMap、以及 ConcurrentHashMap 可以实现线程安全的 Map。

  • HashTable 是直接在操作方法上加 synchronized 关键字,锁住整个table数组,粒度比较大;
  • Collections.synchronizedMap 是使用 Collections 集合工具的内部类,通过传入 Map 封装出一个 SynchronizedMap 对象,内部定义了一个对象锁,方法内通过对象锁实现;
  • ConcurrentHashMap 在jdk1.7中使用分段锁,在jdk1.8中使用CAS+synchronized。

HashMap 内部节点是有序的吗?

HashMap是无序的,根据 hash 值随机插入。如果想使用有序的Map,可以使用 LinkedHashMap 或者 TreeMap。

LinkedHashMap 怎么实现有序的?

LinkedHashMap维护了一个双向链表,有头尾节点,同时 LinkedHashMap 节点 Entry 内部除了继承 HashMap 的 Node 属性,还有 before 和 after 用于标识前置节点和后置节点。可以实现按插入的顺序或访问顺序排序。
在这里插入图片描述

TreeMap 怎么实现有序的?

TreeMap 是按照 Key 的自然顺序或者 Comprator 的顺序进行排序,内部是通过红黑树来实现。所以要么 key 所属的类实现 Comparable 接口,或者自定义一个实现了Comparator 接口的比较器,传给 TreeMap 用于 key 的比较。
在这里插入图片描述

Set

讲讲HashSet的底层实现?

HashSet 底层就是基于 HashMap 实现的。(HashSet的源码非常少,因为除了clone()、writeObject()、readObject()是HashSet自己不得不实现之外,其他方法都是直接调用HashMap中的方法。)

HashSet的add方法,直接调用HashMap的put方法,将添加的元素作为key,new一个 Object作为value,直接调用HashMap的put方法,它会根据返回值是否为空来判断是否插入元素成功。

public boolean add(E e) {return map.put(e, PRESENT) == null;
}

在这里插入图片描述

而在HashMap的putVal方法中,进行了一系列判断,最后的结果是,只有在key在table数组中不存在的时候,才会返回插入的值。

if (e != null) {	// existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null) {e.value = value;}afterNodeAccess(e);return oldValue;
}

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

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

相关文章

国内外遥感数据处理软件对比

1.国内遥感数据处理软件概况 1.1北京航天宏图信息技术股份有限公司 1.1.1公司简介 航天宏图信息技术股份有限公司成立于2008年,是国内遥感和北斗导航卫星应用服务商,致力于卫星应用软件国产化、行业应用产业化、应用服务商业化,研发并掌握了具有完全自主知识产权的PIE(Pix…

Python源码:Tkinter组件布局管理的3种方式

Tkinter组件布局管理可以使用pack()方法、grid()方法和place()方法。pack()方法将组件放置在窗口中&#xff0c;grid()方法将组件放置在网格布局中&#xff0c;place()方法将组件放置在指定位置。 01使用pack()方法布局&#xff1a; 在Tkinter中&#xff0c;pack方法用于将控…

【Git系列】Git到远程仓库

&#x1f433;Git到远程仓库 &#x1f9ca;1. github账号注册&#x1f9ca;2. 初始化本地仓库&#x1f9ca;3. 创建GitHub远程仓库&#x1f9ca;4. 给本地仓库起别名&#x1fa9f;4.1 查看远程库的连接地址&#x1fa9f;4.2 起别名 &#x1f9ca;5. git推送操作&#x1f9ca;6.…

WAF绕过-信息收集篇

WAF绕过主要集中在信息收集&#xff0c;漏洞发现&#xff0c;漏洞利用&#xff0c;权限控制四个阶段。 1、什么是WAF&#xff1f; Web Application Firewall&#xff08;web应用防火墙&#xff09;&#xff0c;一种公认的说法是“web应用防火墙通过执行一系列针对HTTP/HTTPS的安…

【模仿学习】:离线和在线模仿

一、说明 模仿学习&#xff08;Imitation Learning &#xff09;是机器学习的一种&#xff0c;代理通过观察和模仿专家的行为来学习。在这种方法中&#xff0c;为代理提供了一组所需行为的演示或示例&#xff0c;并通过尝试复制专家的行为来学习输入观察和输出操作之间的映射。…

安装win版本的neo4j(2023最新版本)

安装win版本的neo4j 写在最前面安装 win版本的neo4j1. 安装JDK2.下载配置环境变量&#xff08;也可选择直接点击快捷方式&#xff0c;就可以不用配环境了&#xff09;3. 启动neo4j 测试代码遇到的问题及解决&#xff08;每次环境都太离谱了&#xff0c;各种问题&#xff09;连接…

【linux 结束pts/1踢人踢除另一个终端】

centos7上误执行了个命令&#xff0c;导致一直刷屏&#xff0c;强制CTRLC无法正常退出&#xff0c;一直出现如下&#xff1a; 网上搜索通过ctrlD&#xff0c;q均无法正常退出&#xff0c; 不想强行关掉&#xff0c;通过&#xff1a;who命令查看均用户&#xff1a; who mshns…

java 企业工程管理系统软件源码+Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

&#xfeff; Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&am…

从 0 到 1!得物如何打造通用大模型训练和推理平台

1.背景 近期&#xff0c;GPT 大模型的发布给自然语言处理&#xff08;NLP&#xff09;领域带来了令人震撼的体验。随着这一事件的发生&#xff0c;一系列开源大模型也迅速崛起。依据一些评估机构的评估&#xff0c;这些开源模型大模型的表现也相当不错。一些大模型的评测情况可…

【ChatGPT辅助学Rust | 基础系列 | 基础语法】变量,数据类型,运算符,控制流

文章目录 简介&#xff1a;一&#xff0c;变量1&#xff0c;变量的定义2&#xff0c;变量的可变性3&#xff0c;变量的隐藏 二、数据类型1&#xff0c;标量类型2&#xff0c;复合类型 三&#xff0c;运算符1&#xff0c;算术运算符2&#xff0c;比较运算符3&#xff0c;逻辑运算…

算法通过村第二关-链表白银笔记|指定区间反转

文章目录 前言链表反转|指定区间内头插法&#xff1a;穿针引线法&#xff1a; 总结 前言 提示&#xff1a;人啊&#xff0c;果然跟花一样&#xff0c;开花前的等待无比漫长&#xff0c;绽放的魅力却转瞬即逝。 链表反转|指定区间内 参考题目&#xff1a;92. 反转链表 II - 力…

超详细 | 模拟退火算法及其MATLAB实现

模拟退火算法(simulated annealing&#xff0c;SA)是20世纪80年代初期发展起来的一种求解大规模组合优化问题的随机性方法。它以优化问题的求解与物理系统退火过程的相似性为基础&#xff0c;利用Metropolis算法并适当地控制温度的下降过程实现模拟退火&#xff0c;从而达到求解…

IO流简述

IO流IO流使用场景 什么是IO流常用的IO流字节流字符流缓冲流 BIO、NIO、AIO的区别 IO流 IO流使用场景 如果操作的是纯文本文件&#xff0c;优先使用字符流如果操作的是图片、视频、音频等二进制文件。优先使用字节流如果不确定文件类型&#xff0c;优先使用字节流。字节流是万能…

vue2实现一个树型控件(支持展开树与checkbox勾选)

目录 vue2实现一个树型控件(支持展开树与checkbox勾选)TreeItem.vueTree.vue效果 vue2实现一个树型控件(支持展开树与checkbox勾选) TreeItem.vue <template><div class"tree-item"><span click"toggleExpanded" class"icon" v…

如何将论文中的字快速复制出来?图片如何提取文字?

在日常的办公中&#xff0c;我们经常会遇到需要将纸质文件里的文字提取出来&#xff0c;再转换为电子档的情况&#xff0c;如果我们采用手动输入的话&#xff0c;不仅速度太慢&#xff0c;而且还可能因此耽误到后边的工作&#xff0c;是不是已经有小伙伴遇到这种现象&#xff0…

Redis以及Java使用Redis

一、Redis的安装 Redis是一个基于内存的 key-value 结构数据库。 基于内存存储&#xff0c;读写性能高 适合存储热点数据&#xff08;热点商品、资讯、新闻&#xff09; 企业应用广泛 官网&#xff1a;https://redis.io 中文网&#xff1a;https://www.redis.net.cn/ Redis…

mysql的日期类型的数据转换为年或者月类型的统计

SELECT CONCAT(YEAR(DATE), if (MONTH(DATE)<10,CONCAT(0,MONTH(DATE)),MONTH(DATE))) AS date , round(SUM(capacity),2) AS ca_dsoc FROM dianchi4 where date > 20211231 GROUP BY YEAR(DATE), MONTH(DATE) 月度的跨年处理就是第一个

文本怎么用手机生成二维码?二维码在线文本码制作技巧

现在二维码可以展示的内容越来越丰富&#xff0c;比如文本就是很常见的一种形式。编辑好文本内容之后&#xff0c;将文字内容添加到二维码中&#xff0c;其他人扫码就可以获取到文字内容&#xff0c;那么文本二维码该如何制作呢&#xff1f;想要制作二维码&#xff0c;那么可以…

SpringCloud集成OpenTelemetry的实现

SpringCloud项目做链路追踪&#xff0c;比较常见的会集成SleuthZipKin来完成&#xff0c;但这次的需求要集成开源框架OpenTelemetry&#xff0c;这里整理下实现过程。相关文章&#xff1a; 【SpringCloud集成SleuthZipkin进行链路追踪】 【OpenTelemetry框架Trace部分整理】 …

百度地图点标记加调用

先看效果 PHP代码 <?phpnamespace kds_addons\edata\controller;use think\addons\Controller; use think\Db;class Maps extends Controller {// 经纬度计算面积function calculate_area($points){$totalArea 0;$numPoints count($points);if ($numPoints > 2) {f…