Java集合框架进阶学习(ArrayList源码分析、HashMap实现原理)

news2024/11/24 23:08:14

文章目录

  • 1、算法复杂度
    • 1.1、时间复杂度分析
    • 1.2、空间复杂度
      • 小总结
  • 2、List
    • 2.1、数组
      • 小总结
    • 2.2、ArrayList源码分析
    • 2.3、单向链表
    • 2.4、双向链表
      • 小总结
  • 3、HashMap
    • 3.1、二叉树
      • 小总结
    • 3.2、散列表
      • 小总结
    • 3.3、HashMap的实现原理
    • 3.4、HashMap的put方法的具体流程
    • 3.5、HashMap的扩容机制
    • 3.6、hashMap的寻址算法
      • 小总结
    • 3.7、多线程死循环问题

思维导图
在这里插入图片描述

在学习集合框架之前,我们先来了解数据结构

1、算法复杂度

1.1、时间复杂度分析

时间复杂度分析:用来估代码的执行耗时

在这里插入图片描述

大O表示法:不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势

T(n)与代码的执行次数成正比(代码行数越多,执行时间越长)

在这里插入图片描述

当n很大时,公式中的低阶,常量,系数三部分并不左右其增长趋势,因此可以忽略,我们只需要记录一个最大的量级就可以了

常见复杂度表示形式

在这里插入图片描述

常见复杂度

在这里插入图片描述

总结:只要代码的执行时间不随着n的增大而增大,这样的代码复杂度都是O(1)

在这里插入图片描述

我们接着往下看,

在这里插入图片描述

在这里插入图片描述

总结

常见的时间复杂度有

O(1)、O(n)、O(n^2)、O(logn)、O(n * logn)

在这里插入图片描述

1.2、空间复杂度

空间复杂度全称是渐进空间复杂度,表示算法占用的额外存储空间数据规模之间的增长关系

在这里插入图片描述

我们常见的空间复杂度就是O(1),O(n),O(n ^2),其他像对数阶的复杂度几乎用不到,因此空间复杂度比时间复杂度分析要简单的多。

小总结

1、什么是时间复杂度?

时间复杂度描述的是算法的执行时间与数据规模之间的增长关系。

2、常见的时间复杂度有哪些?

O(1)、O(n)、O(n^2)、O(logn)

3、什么是算法的空间复杂度?

表示算法占用的额外存储空间与数据规模之间的增长关系

常见的空间复杂度:O(1),O(n),O(n ^2)

2、List

2.1、数组

数组(Array)是一种用连续的内存空间存储相同数据类型数据的线性数据结构

在这里插入图片描述

数组如何获取其他元素的地址值?

在这里插入图片描述

为什么数组索引从0开始呢?假如从1开始不行吗?

在这里插入图片描述

操作数组的时间复杂度(查找)

1.随机查询(根据索引查询)

数组元素的访问是通过下标访问的,计算机通过数组的首地址和寻址公式能够很快速的找到想要访问的元素
在这里插入图片描述

2. 未知索引查询

情况一:查找数组内的元素,查找55号数据

在这里插入图片描述

情况二:查找排序后数组内的元素,查找55号数据

在这里插入图片描述

操作数组的时间复杂度(插入、删除)

数组是一段连续的内存空间,因此为了保证数组的连续性会使得数组的插入和删除的效率变的很低。

在这里插入图片描述

小总结

  1. 数组(Array)是一种用连续的内存空间存储相同数据类型数据的线性数据结构

  2. 数组下标为什么从0开始

    寻址公式是:baseAddress + i * dataTypeSize , 计算下标的内存地址效率很高

  3. 查找到时间复杂度

    • 随机(通过下标)查找的时间复杂度是O(1)
    • 查找元素(未知元素)的时间复杂度是O(n)
    • 查找元素(未知下标但有序)通过二分查找的时间复杂度是O(logn)
  4. 插入和删除的时间复杂度

    插入和删除的时候,为了保证数组的内存连续性,需要挪动数组元素,平均的时间复杂度为O(n)

2.2、ArrayList源码分析

源码如何分析呢?

在这里插入图片描述

我们可以从三个方面去分析源码:

  1. 成员变量
  2. 构造方法
  3. 关键方法

ArrayList源码分析-成员变量

在这里插入图片描述

ArrayList源码分析-构造方法

在这里插入图片描述

ArrayList源码分析-添加和扩容操作

第1次添加数据

在这里插入图片描述

第2至10次添加数据

在这里插入图片描述

第11次添加数据

在这里插入图片描述

ArrayList底层的实现原理是什么?

  • 底层数据结构

    ArrayList底层是用动态的数组实现的

  • 初始容量

    ArrayList初始容量为0,当第一次添加数据的时候才会初始化数据为10

  • 扩容逻辑

    ArrayList在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组

  • 添加逻辑

    • 确保数组已使用长度(size)加1之后足够存下下一条数据
    • 计算数组的容量,如果当前数组已使用长度加1后大于当前的数组长度,则调用grow方法扩容(原来的1.5倍)
    • 确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上
    • 返回添加成功布尔值

Arrayist list=new ArrayList(10)中的list扩容几次?

看源码:

该语句只是声明和实例了一个 ArrayList,指定了容量为 10,未扩容

如何实现数组和List之间的转换?

在这里插入图片描述

  • 数组转List,使用JDK中的java.util.Arrays包工具类的asList方法
  • List转数组,使用List的toArray方法。无参toArray方法返回一个Object数组,传入初始化长度的数组对象,返回该对象数组

用Arrays.asList转List后,如果修改了数组内容,list受影响吗

List用toArray转数组后,如果修改了List内容,数组受影响吗

在这里插入图片描述

  • Arrays.asList转换list之后,如果修改了数组的内容,list会受影响,因为它的底层使用的Arrays类中的一个内部类ArrayList来构造的集合,在这个集合的构造器中,把我们传入的这个集合进行了包装而已,最终指向的都是同一个内存地址

  • list用了toArray转数组后,如果修改了list内容,数组不会影响,当调用了toArray以后,在底层是它是进行了数组的拷贝,跟原来的元素就没啥关系了,所以即使list修改了以后,数组也不受影响

2.3、单向链表

单向链表

  • 链表中的每一个元素称之为节点(Node)
  • 物理存储单元上,非连续,非顺序的存储结构
  • 单向链表:每个节点包括两个部分,一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。记录下个节点地址的指针叫做后继指针(next)

在这里插入图片描述

代码实现

在这里插入图片描述

单向链表时间复杂度分析

查询操作

在这里插入图片描述

  • 只有在查询头结点的时候不需要遍历链表,时间复杂度是O(1)
  • 查询其他节点需要遍历链表,时间复杂度为O(n)

插入/删除操作

在这里插入图片描述

  • 只有在添加和删除头节点的时候不需要遍历链表,时间复杂度是O(1)
  • 添加或删除其他节点需要遍历链表找到对应节点后,才能完成新增或删除节点,时间复杂度是O(n)

2.4、双向链表

而双向链表,顾名思义,它支持两个方向

  • 每个结点不止有一个后继指针 next 指向后面的结点

  • 有一个前驱指针 prev 指向前面的结点

在这里插入图片描述

在这里插入图片描述

对比单链表:

  • 双向链表需要额外的两个空间来存储后继结点和前驱结点的地址

  • 支持双向遍历,这样也带来了双向链表操作的灵活性

时间复杂度分析

在这里插入图片描述

小总结

  1. 单向链表和双向链表的区别是什么?

    • 单向链表只有一个方向,结点只有一个后继指针 next。
    • 双向链表它支持两个方向,每个结点不止有一个后继指针next指向后面的结点,还有一个前驱指针prev指向前面的结点
  2. 链表操作数据的时间复杂度是多少?

    • 单向链表 头O(1),其他O(n)
    • 双向链表 头尾O(1),其他O(n),给定节点O(1)

ArrayList 和 LinkedList 的区别是什么?

在这里插入图片描述

在这里插入图片描述

3、HashMap

3.1、二叉树

二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只有左子节点,有的节点只有右子节点。

二叉树每个节点的左子树和右子树也分别满足二叉树的定义。

在这里插入图片描述

Java中有两个方式实现二叉树:数组存储,链式存储。

基于链式存储的树的节点可定义如下:

在这里插入图片描述

在二叉树中,比较常见的二叉树有:

  • 满二叉树

  • 完全二叉树

  • 二叉搜索树

  • 红黑树

我们重点看一下二叉搜索树和红黑树

二叉搜索树

二叉查找树要求,在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值

在这里插入图片描述

实际上由于二叉查找树的形态各异,时间复杂度也不尽相同,我画了几棵树我们来看一下插入,查找,删除的时间复杂度

在这里插入图片描述

在这里插入图片描述

下面我们看一下红黑树

红黑树(Red Black Tree):也是一种自平衡的二叉搜索树(BST),之前叫做平衡二叉B树(Symmetric Binary B-Tree)

在这里插入图片描述

红黑树的特点

性质1:节点要么是红色,要么是黑色

性质2:根节点是黑色

性质3:叶子节点都是黑色的空节点

性质4:红黑树中红色节点的子节点都是黑色

性质5:从任一节点到叶子节点的所有路径都包含相同数目的黑色节点

在添加或删除节点的时候,如果不符合这些性质会发生旋转,以达到所有的性质,保证平衡

红黑树的复杂度分析:

  • 查找:

    红黑树也是一棵BST(二叉搜索树)树,查找操作的时间复杂度为:O(log n)

  • 添加:

    添加先要从根节点开始找到元素添加的位置,时间复杂度O(log n)

    添加完成后涉及到复杂度为O(1)的旋转调整操作

    故整体复杂度为:O(log n)

  • 删除:

    首先从根节点开始找到被删除元素的位置,时间复杂度O(log n)

    删除完成后涉及到复杂度为O(1)的旋转调整操作

    故整体复杂度为:O(log n)

小总结

1.什么是二叉树?

  • 每个节点最多有两个“叉”,分别是左子节点和右子节点。

  • 不要求每个节点都有两个子节点,有的节点只有左子节点,有的节点只有右子节点。

  • 二叉树每个节点的左子树和右子树也分别满足二叉树的定义

2.什么是二叉搜索树?

  • 二叉搜索树(Binary Search Tree,BST)又名二叉查找树,有序二叉树

  • 在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值而右子树节点的值都大于这个节点的值

  • 没有键值相等的节点

  • 通常情况下二叉树搜索的时间复杂度为O(logn)

3.什么是红黑树?

  • 红黑树(Red Black Tree):也是一种自平衡的二叉搜索树(BST)

  • 所有的红黑规则都是希望红黑树能够保证平衡

  • 红黑树的时间复杂度:查找、添加、删除都是O(logn)

3.2、散列表

在HashMap中的最重要的一个数据结构就是散列表,在散列表中又使用到了红黑树和链表

散列表(Hash Table)又名哈希表/Hash表,是根据键(Key)直接访问在内存存储位置值(Value)的数据结构,它是由数组演化而来的,利用了数组支持按照下标进行随机访问数据的特性

假设有100个人参加马拉松,不采用1-100的自然数对选手进行编号,编号有一定的规则比如:2023ZHBJ001,其中2023代表年份,ZH代表中国,BJ代表北京,001代表原来的编号,那此时的编号2023ZHBJ001不能直接作为数组的下标,此时应该如何实现呢?

在这里插入图片描述

将键(key)映射为数组下标的函数叫做散列函数。可以表示为:hashValue = hash(key)

散列函数的基本要求:

  • 散列函数计算得到的散列值必须是大于等于0的正整数,因为hashValue需要作为数组的下标。

  • 如果key1==key2,那么经过hash后得到的哈希值也必相同即:hash(key1) == hash(key2)

  • 如果key1 != key2,那么经过hash后得到的哈希值也必不相同即:hash(key1) != hash(key2)

散列冲突

实际的情况下想找一个散列函数能够做到对于不同的key计算得到的散列值都不同几乎是不可能的

即便像著名的MD5,SHA等哈希算法也无法避免这一情况,这就是散列冲突(或者哈希冲突,哈希碰撞,就是指多个key映射到同一个数组下标位置)

在这里插入图片描述

散列冲突-链表法(拉链)

在散列表中,数组的每个下标位置我们可以称之为桶(bucket)或者槽(slot),每个桶(槽)会对应一条链表,所有散列值相同的元素我们都放到相同槽位对应的链表中。

在这里插入图片描述

散列冲突-链表法(拉链)- 时间复杂度

  1. 插入操作,通过散列函数计算出对应的散列槽位,将其插入到对应链表中即可,插入的时间复杂度是 O(1)

  2. 当查找、删除一个元素时,我们同样通过散列函数计算出对应的槽,然后遍历链表查找或者删除

    • 平均情况下基于链表法解决冲突时查询的时间复杂度是O(1)
    • 散列表可能会退化为链表,查询的时间复杂度就从 O(1) 退化为 O(n)
    • 将链表法中的链表改造为其他高效的动态数据结构,比如红黑树,查询的时间复杂度是 O(logn)

将链表法中的链表改造红黑树还有一个非常重要的原因,可以防止DDos攻击

DDos 攻击:

可以理解为有人恶意攻击,伪造了很多的key,造成了hash冲突,就会在数组的索引中产生大量的链表,导致在访问散列表的时候效率非常慢。

小总结

  1. 什么是散列表?
    • 散列表(Hash Table)又名哈希表/Hash表
    • 根据键(Key)直接访问在内存存储位置值(Value)的数据结构
    • 由数组演化而来的,利用了数组支持按照下标进行随机访问数据
  2. 散列冲突
    • 散列冲突又称哈希冲突,哈希碰撞
    • 指多个key映射到同一个数组下标位置
  3. 散列冲突-链表法(拉链)
    • 数组的每个下标位置称之为桶(bucket)或者槽(slot)
    • 每个桶(槽)会对应一条链表
    • hash冲突后的元素都放到相同槽位对应的链表中或红黑树中

3.3、HashMap的实现原理

HashMap实现原理?

HashMap的数据结构: 底层使用hash表数据结构,即数组+(链表 | 红黑树)

  1. 当我们往HashMap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标

  2. 存储时,如果出现hash值相同的key,此时有两种情况。

    a. 如果key相同,则覆盖原始值;

    b. 如果key不同(出现冲突),则将当前的key-value放入链表或红黑树中

  3. 获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

简单来说:

  • 底层使用hash表数据结构,即数组+(链表 | 红黑树)

  • 添加数据时,计算key的值确定元素在数组中的下标

    • key相同则替换
    • 不同则存入链表或红黑树中

    获取数据通过key的hash计算数组下标获取元素

HashMap的jdk1.7和jdk1.8有什么区别?

  • JDK1.8之前采用的是拉链法。拉链法:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
  • jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8) 时并且数组长度达到64时,将链表转化为红黑树,以减少搜索时间。扩容 resize( ) 时,红黑树拆分成的树的结点数小于等于临界值6个,则退化成链表

在这里插入图片描述

一句话:

  • JDK1.8之前采用的拉链法,数组+链表
  • JDK1.8之后采用数组+链表+红黑树,链表长度大于8且数组长度大于64则会从链表转化为红黑树

3.4、HashMap的put方法的具体流程

HashMap源码分析-常见属性

在这里插入图片描述

在这里插入图片描述

  • HashMap是懒惰加载,在创建对象时并没有初始化数组

  • 在无参的构造函数中,设置了默认的加载因子是0.75

添加数据流程图

在这里插入图片描述

HashMap的put方法的具体流程

  1. 判断键值对数组table是否为空或为null,否则执行resize()进行扩容(初始化)

  2. 根据键值key计算hash值得到数组索引

  3. 判断table[i]==null,条件成立,直接新建节点添加

  4. 如果table[i]==null ,不成立

    • 判断table[i]的首个元素是否和key一样,如果相同直接覆盖value
    • 判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对
    • 遍历table[i],链表的尾部插入数据,然后判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操 作,遍历过程中若发现key已经存在直接覆盖value
  5. 插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold(数组长度*0.75),如果超过,进行扩容。

3.5、HashMap的扩容机制

在这里插入图片描述

扩容的流程

在这里插入图片描述

  1. 在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次每次扩容都是达到了扩容阈值(数组长度 * 0.75)

  2. 每次扩容的时候,都是扩容之前容量的2倍;

  3. 扩容之后,会新创建一个数组,需要把老数组中的数据挪动到新的数组中

    • 没有hash冲突的节点,则直接使用 e.hash & (newCap - 1) 计算新数组的索引位置
    • 如果是红黑树,走红黑树的添加
    • 如果是链表,则需要遍历链表,可能需要拆分链表,判断(e.hash & oldCap)是否为0,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上

3.6、hashMap的寻址算法

hashMap的寻址算法

在这里插入图片描述

为何HashMap的数组长度一定是2的次幂?

  1. 计算索引时效率更高:如果是 2 的 n 次幂可以使用位与运算代替取模

  2. 扩容时重新计算索引效率更高: hash & oldCap == 0 的元素留在原来位置 ,否则新位置 = 旧位置 + oldCap

小总结

  1. hashMap的寻址算法

    • 计算对象的 hashCode()
    • 再进行调用 hash() 方法进行二次哈希, hashcode值右移16位再异或运算,让哈希分布更为均匀
    • 最后 (capacity – 1) & hash 得到索引
  2. 为何HashMap的数组长度一定是2的次幂?

    • 计算索引时效率更高:如果是 2 的 n 次幂可以使用位与运算代替取模
    • 扩容时重新计算索引效率更高: hash & oldCap == 0 的元素留在原来位置 ,否则新位置 = 旧位置 + oldCap

3.7、多线程死循环问题

hashmap在1.7情况下的多线程死循环问题

jdk7的的数据结构是:数组+链表

在数组进行扩容的时候,因为链表是头插法,在进行数据迁移的过程中,有可能导致死循环

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在jdk1.7的hashmap中在数组进行扩容的时候,因为链表是头插法,在进行数据迁移的过程中,有可能导致死循环

比如说,现在有两个线程

线程一:读取到当前的hashmap数据,数据中一个链表,在准备扩容时,线程二介入

线程二:也读取hashmap,直接进行扩容。因为是头插法,链表的顺序会进行颠倒过来。比如原来的顺序是AB,扩容后的顺序是BA,线程二执行结束。

线程一:继续执行的时候就会出现死循环的问题。

线程一先将A移入新的链表,再将B插入到链头,由于另外一个线程的原因,B的next指向了A,所以B->A->B,形成循环。

当然,JDK 8 将扩容算法做了调整,不再将元素加入链表头(而是保持与扩容前一样的顺序),尾插法,就避免了jdk7中死循环的问题。

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

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

相关文章

简历石沉大海!这份新鲜出炉的测试用人需求分析报告揭示了原因

最近有朋友吐槽简历投递后石沉大海,而主动打电话面试的除了外包还是外包。软件测试就业形势真的这么糟糕了? 小酋决定用数据揭开真相。因此小酋选取“软件测试”、“自动化测试”、“测试开发”作为搜索关键词,统计了 无忧网 近一个月用人市…

目标跟踪基础:两张图片相似度算法

本文来自公众号“AI大道理” —————— 目标跟踪就是在时序帧中搜索目标的过程,本质上就是检索。 不管是传统的目标跟踪中的生成模型和判别模型,还是用深度学习来做目标跟踪,本质上都是来求取目标区域与搜索区域的相似度,这就…

C# 依赖倒置原则(DIP)

目录 一,引子 1.1 传统的程序架构 1.2 依赖倒置 1.3 依赖倒置的作用 二,依赖注入 一,引子 1.1 传统的程序架构 在程序执行过程中,传统的程序架构如图: 可以看到,在传统的三层架构中,层与…

CSS的学习4(盒子模型及浮动)

CSS的学习3:http://t.csdn.cn/xDxIJ 盒子模型 网页布局过程 先准备好相关的网页元素,网页元素基本都是盒子Box利用CSS设置好盒子样式,然后摆放到相应位置往盒子里面装内容 封装周围的HTML元素: 边框(border&#…

[网鼎杯 2020 青龙组]AreUSerialz1

代码审计 得到一大串源码&#xff0c;但是不要慌&#xff0c;虽然源码很多&#xff0c;其实题目并不难 这段代码是一个简单的文件读写类 FileHandler&#xff0c;以及一个反序列化函数 unserialize() 的使用。 <?phpinclude("flag.php");highlight_file(__FILE__…

Stable Diffusion 中英文对照中文tag补全

Stable Diffusion是老外做的&#xff0c;因此全部界面都是英文的&#xff0c;因此会对国内很多英语不好的小伙伴来说是一个灾难&#xff0c;不过这里介绍大家一个自定义翻译插件的方法如下图。 还有我们在输入关键词的时候&#xff0c;由于英语水平有限对我们造成阻碍&#xf…

QTTCP客户端服务端通信

目录 网络模块介绍 TCP介绍 TCP 服务端应用实例 TCP 客户端应用实例 运行结果&#xff1a; 网络模块介绍 Qt 网络模块为我们提供了编写 TCP / IP 客户端和服务器的类。它提供了较低级别的类&#xff0c;例 如代表低级网络概念的 QTcpSocket &#xff0c; QTcpServer 和 …

智慧旅游卡APP小程序开发方案

旅游业的蓬勃发展&#xff0c;旅游卡作为一种便捷的旅游支付方式越来越受到人们的喜爱。智慧旅游卡APP小程序开发方案是一种利用微信小程序实现的在线购买旅游卡、查询旅游信息、预约旅游服务等功能的旅游卡APP。下面将详细介绍智慧旅游卡APP小程序的开发方案。 一、智慧旅…

【CDC 2023 Cooperative Aerial Robots Inspection Challenge】

CDC 2023 Cooperative Aerial Robots Inspection Challenge 合作空中机器人检查挑战赛 Install the CARIC packagesRun the flight testThe benchmark designThe UAV fleet CDC 2023 Cooperative Aerial Robots Inspection Challenge 网址 Install the CARIC packages Once t…

旅游卡APP开发解决方案

旅游业的不断发展&#xff0c;旅游卡成为了人们出行时必不可少的一项工具。旅游卡APP开发解决方案旨在为用户提供更加便捷、高效的旅游卡购买和使用体验。下面将详细介绍旅游卡APP开发解决方案的几个方面。 一、旅游卡APP开发解决方案的技术方面 旅游卡APP开发解决方案…

Python pyecharts实时画图自定义可视化经纬度热力图

目录 背景基于pyecharts内置经纬度的热力图基于自定义经纬度的热力图pyecharts库缺点不同地图坐标系区别 WGS-84 - 世界大地测量系统GCJ-02 - 国测局坐标BD-09 - 百度坐标系 背景 在业务数据统计分析中基本都会涉及到各省区的分析&#xff0c;数据可视化是数据分析的一把利器…

事件机制(事件流、事件委托、事件类型)

HTML DOM 允许 JavaScript 对 HTML 事件作出反应。JavaScript 能够在事件发生时执行&#xff0c;比如当用户点击某个 HTML 元素时。 JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。 目录 事件是由三部分组成 执行事件的步…

儿童硅胶勺子LFGB标准检测是什么?

食品级硅胶制品的德国食品接触材料测试LFGB标准检测哪些项目&#xff1f; Sensory test感官测试一味道和气味对于与食品接触的整体产品 extractable components in ethanol(Ethanol as compulsory simulant)(must perform)10%酒精萃取法(必做) Extractable component in deioni…

官网能为企业营销增长贡献哪些力量?

官网是门面&#xff0c;同时也具备营销价值&#xff0c;可以带来流量转化成销售线索&#xff0c;影响公司营收&#xff0c;B2B业务是复杂的&#xff0c;客户在选择你之前会长期的研究你的官网&#xff0c;了解你的产品及服务、成功案例、甚至是品牌的创始团队信息&#xff0c;来…

SpringCloud学习1

SpringCloud是分布式微服务架构的 一些列解决方案的集合&#xff0c;SpringBoot是一门单独的技术 ​​​​​​

小心 MybatisPlus 的一个坑与面试题

昨天测试说有个 xx 功能用不了&#xff0c;扔给我一个截图&#xff0c;说有报错&#xff1a; 报错信息就是&#xff1a;Transaction rolled back because it has been marked as rollback-only&#xff0c;很好理解&#xff1a;事务被回滚了&#xff0c;因为它已经被标记了只能…

HttpRunner自动化之请求中带有 headers 的接口和发送POST请求

headers 可通过headers 添加头部信息&#xff0c;如下图 # 发送请求头headers的接口 - config:name: 百度接口用例base_url: https://www.baidu.com- test:name: 发送百度接口的头部信息request:url: /smethod: GETheaders:Accept: text/html,application/xhtmlxml,applicati…

LNMT(linux下nignx+mysql+tomcat(中间件)应用)部署应用、及各服务介绍、部署开源站点jpress

目录 一、环境准备 二、tomcat1和tomcat2服务器&#xff0c;安装配置tomcat 1.tomcat服务器介绍 2.JDK软件介绍 3.查看JDK是否安装 4.tomcat1和tomcat2服务器&#xff0c;安装JDK1.8.0_191&#xff08;JDK必须和nginx版本相适应&#xff0c;不然一直报错&#xff09; 5.安…

【LeetCode】HOT 100(21)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

源启数据资产管理平台助力金融机构加速数据资产化过程

自2000年左右&#xff0c;金融行业开始做数据管理。从数据仓库到数据治理、数据应用&#xff0c;再到后来的大数据&#xff0c;以及今天的数据管理。我们把这个时期总结成数据资产化时代&#xff0c;或者叫国产化时代。 为什么有两个名字&#xff1f;数据资产化时代是因为国家…