图文并茂java源码解析-HashMap

文章目录

  • HashMap结构
    • HashMap的Entry
    • 了解的哈希冲突解决方法有哪些?
    • HashMap是线程安全的吗?
    • hashmap的put过程介绍一下
      • jdk8的获取hash的方法
      • jdk8的获取索引的方法
    • hashmap的put过程介绍一下
    • hashmap 调用get方法一定安全吗?
    • HashMap一般用什么做Key?为啥String适合做Key呢?
    • 为什么HashMap要用红黑树而不是平衡二叉树?
    • hashmap key可以为null吗?
    • hashmap用头插法还是尾插法?
    • 列举HashMap在多线程下可能会出现的问题?
    • 重写HashMap的equal和hashcode方法需要注意什么?
    • 重写HashMap的equal方法不当会出现什么问题?
    • HashMap的扩容机制介绍一下
    • 往hashmap存20个元素,会扩容几次?
    • 说说hashmap的负载因子
    • Hashmap和Hashtable有什么不一样的?

HashMap结构

java7用的数组+链表
java8用的数组+链表+红黑树
因为数组有定位快,增加元素快,但是remove费劲的特点,链表有删除元素快,头尾增加快,但是定位元素慢的特点,因此HashMap结合两者优点应运而生.在实际中应用很多!
在这里插入图片描述

HashMap的Entry

在这里插入图片描述
Entry存储了K,V,Hash,以及下一个Entry的引用。

在 JDK 1.7 版本之前, HashMap 数据结构是数组和链表,HashMap通过哈希算法将元素的键(Key)映射到数组中的槽位(Bucket)。如果多个键映射到同一个槽位,它们会以链表的形式存储在同一个槽位上,因为链表的查询时间是O(n),所以hash冲突很严重,一个索引上的链表非常长,效率就很低了。
所以在 JDK 1.8 版本的时候做了优化,当一个链表(不算桶)的 L ≥ 8 L\ge 8 L8的时候就转换数据结构,不再使用链表存储,而是使用红黑树,查找时使用红黑树,时间复杂度 O ( l o g n ) O(logn) O(logn),可以提高查询性能,但是在数量较少时,即数量(不算桶) L ≤ 6 L\le 6 L6时,会将红黑树转换回链表。

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

  • 链接法:使用链表或其他数据结构来存储冲突的键值对,将它们链接在同一个哈希桶中。
  • 开放寻址法:在哈希表中找到另一个可用的位置来存储冲突的键值对,而不是存储在链表中。常见的开放寻址方法包括
    线性探测、二次探测和双重散列。
  • 再哈希法(Rehashing):当发生冲突时,使用另一个哈希函数再次计算键的哈希值,直到找到一个空槽来存储键值对。
  • 哈希桶扩容:当哈希冲突过多时,可以动态地扩大哈希桶的数量,重新分配键值对,以减少冲突的概率。

HashMap是线程安全的吗?

hashmap不是线程安全的,hashmap在多线程会存在下面的问题:

  • JDK 1.7 HashMap 采用数组 +链表的数据结构,多线程背景下在数组扩容的时候,存在 Entry 链死循环和数据丢失问题。
  • JDK 1.8 HashMap 采用数组 +链表+红黑二又树的数据结构,优化了 1.7 中数组扩容的方案,解决了 Entry 链死循环和数据丢失问题。但是多线程背景下,put 方法存在数据覆盖的问题。
    如果要保证线程安全,可以通过这些方法来保证:
  • 多线程环境可以使用Collections.synchronizedMap同步加锁的方式,还可以使用HashTable,但是同步的方式显然性能不达标,而ConurrentHashMap更适合高并发场景使用。
  • ConcurrentHashmap在JDK1.7和1.8的版本改动比较大,1.7使用Segment+HashEntry分段锁的方式实现,1.8则抛弃了Segment改为使用CAS+synchronized+Node实现,同样也加入了红黑树避免链表过长导致性能的问题。

hashmap的put过程介绍一下

在这里插入图片描述

jdk8的获取hash的方法

把原来key的HashCode方法得到的值存到h里面,然后h ^ (h>>>16),意思是把h无符号右移16位,把原来h的16位高位挪到16低位里面,然后高位16用0填充这个数我们用h2存储,h2 = h>>>16,然后h ^ h2,这样h ^ h2得到的才是hash结果。这样操作充分利用到了key的高位,可以更加的随机位置插入元素了

jdk8的获取索引的方法

先保证数组长度n始终为 2 k , k ∈ 自然数 N ≥ 4 2^k,k \in 自然数N \ge 4 2k,k自然数N4,一般来说默认无参构造函数创建数组长度16,负载因子0.75.
当数组长度始终为2的k次幂的时候, ( n − 1 ) & h a s h (n-1) \& hash (n1)&hash等于 h a s h % n hash \% n hash%n,计算机里面%运算比减法和&运算的复合复杂度要高,因此采用 ( n − 1 ) & h a s h (n-1) \& hash (n1)&hash的方式获取索引!此乃结论!直接硬背!

hashmap的put过程介绍一下

第一步:根据要添加的键的哈希码计算在数组中的位置(索引)。
( n − 1 ) & h a s h (n-1) \& hash (n1)&hash

第二步:检查该位置是否为空(即没有键值对存在
如果为空,则直接在该位置创建一个新的Entry对象来存储键值对。将要添加的键值对作为该Entry的K和V,并保存在数组的对应位置。将HashMap的修改次数(modCount)加1,以便在进行迭代时发现并发修改。
在这里插入图片描述

第三步:如果该位置已经存在其他KV对,检查该位置的第一个KV对的哈希码和K是否与要添加的KV对的K相同?
如果相同,则表示找到了相同的键,直接将新的V替换旧的V完成更新操作。

在这里插入图片描述

第四步:如果第一个键值对的哈希码和键不相同,则需要遍历链表或红黑树来查找是否有相同的键

  1. 如果KV对集合是链表List结构,从链表的头部开始逐个比较K的哈希码和equals()方法,直到找到相同的键或达到链表末尾。
  • 如果找到了相同的键,则使用新的值取代旧的值,即更新键对应的值。
  • 如果没有找到相同的键,则将新的Entry添加到链表的头部。
  1. 如果键值对集合是红黑树R结构,在红黑树中使用哈希码和equals()方法进行查找。根据键的哈希码,定位到红黑树中的某个节点,然后逐个比较键,直到找到相同的键或达到红黑树末尾。
  • 如果找到了相同的键,则使用新的值取代旧的值,即更新键对应的值。
  • 如果没有找到相同的键,则将新的Entry添加到红黑树中。

在这里插入图片描述

上图第二个大红框里面判断e.hash == hash的理由是:为了快速过滤掉那些明显不可能匹配的节点

  1. 性能优化:
    快速排除不匹配的节点: 通过比较哈希值,可以快速排除那些哈希值不同的节点,避免不必要的 equals 方法调用。equals 方法通常涉及更多的计算和内存访问,因此比较哈希值可以显著提高性能。
    减少 equals 调用次数: 如果哈希值不同,那么键肯定不同,不需要进一步调用 equals 方法。只有当哈希值相同时,才需要进一步检查键是否相等。
  2. 正确性:
    确保键的唯一性: 即使两个不同的对象可能具有相同的哈希值(哈希碰撞),但它们的键必须完全相同才能被认为是同一个键。因此,先比较哈希值可以确保在调用 equals 方法之前,已经排除了大部分不匹配的情况。

其实我感觉hash值不一样也会导致 ( n − 1 ) & h a s h (n-1)\hspace{0.1cm} \& \hspace{0.1cm}hash (n1)&hash映射到同一位置
h a s h 1 ≠ h a s h 2 , i d x 1 = i d x 2 hash_{1} \neq hash_{2} , idx_1=idx_2 hash1=hash2,idx1=idx2
举个例子,
h a s h 1 & ( n − 1 ) → i d x 1 hash_{1}\hspace{0.1cm}\&\hspace{0.1cm}(n-1) \to idx_1 hash1&(n1)idx1
h a s h 2 & ( n − 1 ) → i d x 2 hash_{2}\hspace{0.1cm}\&\hspace{0.1cm}(n-1) \to idx_2 hash2&(n1)idx2
请添加图片描述

第五步:检查链表长度是否达到阈值(默认为8)
如果链表长度超过阈值,且HashMap的数组长度大于等于64,则会将链表转换为红黑树,以提高查询效率。如果链表长度L>=8且HashMap长度小于64,则执行扩容resize(注意这里ConcurrentHashMap的也是一样的,put元素时数组长度>=64才转List为RB-Tree,否则扩容)

注意:
桶1个,桶后面链8个树化,
桶1个,桶后面链7个不树化。
在这里插入图片描述
在这里插入图片描述

证明所需代码如下:

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
class MyKey {@Override public int hashCode() {return 1;}@Override public boolean equals(Object o) {return false;}
}
class MyVal{@Overridepublic int hashCode() {return 1;}
}
public class Main {public static void main(String[] args) {HashMap map = new HashMap(1024);MyKey k1 = new MyKey();MyKey k2 = new MyKey();MyKey k3 = new MyKey();MyKey k4 = new MyKey();MyKey k5 = new MyKey();MyKey k6 = new MyKey();MyKey k7 = new MyKey();MyKey k8 = new MyKey();MyKey k9 = new MyKey();MyVal v1 = new MyVal();MyVal v2 = new MyVal();MyVal v3 = new MyVal();MyVal v4 = new MyVal();MyVal v5 = new MyVal();MyVal v6 = new MyVal();MyVal v7 = new MyVal();MyVal v8 = new MyVal();MyVal v9 = new MyVal();
//        System.out.println(k1.hashCode());
//        System.out.println(k2.hashCode());
//        System.out.println(k1.equals(k2));map.put(k1,v1);map.put(k2,v2);map.put(k3,v3);map.put(k4,v4);map.put(k5,v5);map.put(k6,v6);map.put(k7,v7);map.put(k8,v8);
//        map.put(k9,v9);System.out.println(map);}
}

第六步:检查负载因子是否超过阈值(默认为0.75):
如果键值对的数量(size)与数组的长度的比值大于阈值,则需要进行扩容操作。

第七步:扩容操作:(可选,非必要,仅当超过负载因此时才扩容)
创建一个新的两倍大小的数组。
将旧数组中的键值对重新计算哈希码并分配到新数组中的位置。
更新HashMap的数组引用和阈值参数。

此外,HashMap是非线程安全的,如果在多线程环境下使用,需要采取额外的同步措施或使用线程安全的ConcurrentHashMap。

hashmap 调用get方法一定安全吗?

不是,调用 get 方法有几点需要注意的地方
空指针异常(NullPointerException):如果你尝试用 null 作为键调用 get方法,而Hashmap 没有被初始化(即为null),那么会抛出空指针异常。不过,如果Hashmap 已经初始化,使用 null 作为键是允许的,因为Hashmap支持 null 键。
线程安全HashMap 本身不是线程安全的。如果在多线程环境中,没有适当的同步措施,同时对Hashmap 进行读写操作可能会导致不可预测的行为。例如,在一个线程中调用get 方法读取数据,而另一个线程同时修改了结构(如增加或删除元素),可能会导致读取操作得到错误的结果或抛出ConcurrentModificationException。如果需要在多线程环境中使用类似 HashMap的数据结构,可以考虑使用
ConcurrentHashMap

HashMap一般用什么做Key?为啥String适合做Key呢?

用 string 做 key,因为 String对象是不可变的,一旦创建就不能被修改,这确保了Key的稳定性。如果Key是可变的,可能会导致hashCode和equals方法的不一致,进而影响HashMap的正确性。

为什么HashMap要用红黑树而不是平衡二叉树?

  • 平衡二叉树追求的是一种“完全平衡”状态:任何结点的左右子树的高度差不会超过1,优势是树的结点是很平均分配的。这个要求实在是太严了,导致每次进行插入/删除节点的时候,几乎都会破坏平衡树的第二个规则,进而我们都需要通过左旋和右旋来进行调整,使之再次成为一颗符合要求的平衡树。
  • 红黑树不追求这种完全平衡状态,而是追求一种“弱平衡”状态:整个树最长路径不会超过最短路径的2倍。优势是虽然牺牲了一部分查找的性能效率,但是能够换取一部分维持树平衡状态的成本。与平衡树不同的是,红黑树在插入、删除等操作,不会像平衡树那样,频繁着破坏红黑树的规则,所以不需要频繁着调整这也是我们为什么大多数情况下使用红黑树的原因。

hashmap key可以为null吗?

可以为 null。

  • hashMap中使用hash()方法来计算key的哈希值,当key为空时,直接另key的哈希值为0,不走key.hashCode()方法
  • hashMap虽然支持key和value为nul,但是nul作为key只能有一个,null作为value可以有多个;
  • 因为hashMap中,如果key值一样,那么会覆盖相同key值的value为最新,所以key为null只能有一个。

hashmap用头插法还是尾插法?

jdk1.7 头插法,多线程会环形链表
jdk1.8 尾插法

列举HashMap在多线程下可能会出现的问题?

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

重写HashMap的equal和hashcode方法需要注意什么?

HashMap使用Key对象的hashCode()和equals方法去决定key-value对的索引。当我们试着从HashMap中获取值的时候,这些方法也会被用到。如果这些方法没有被正确地实现,在这种情况下,两个不同Key也许会产生相同的hashCode()和equals()输出,HashMap将会认为它们是相同的,然后覆盖它们,而非把它们存储到不同的地方
同样的,所有不允许存储重复数据的集合类都使用hashCode0和equals()去查找重复,所以正确实现它们非常重要。equals()和hashCode()的实现应该遵循以下规则:
·如果o1.equals(o2),那么o1.hashCode()== o2.hashcode()总是为true的。
如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)会为true。

重写HashMap的equal方法不当会出现什么问题?

HashMap在比较元素时,会先通过hashCode进行比较,相同的情况下再通过equals进行比较。
所以 equals相等的两个对象,hashCode一定相等。hashCode相等的两个对象,equals不一定相等(比如散列冲突的情况)
重写了equals方法,不重写hashCode方法时,可能会出现equals方法返回为true,而hashCode方法却返回false,这样的一个后果会导致在hashmap等类中存储多个一模一样的对象,导致出现覆盖存储的数据的问题,这与hashmap只能有唯一的key的规范不符合。

HashMap的扩容机制介绍一下

hashMap默认的负载因子是0.75,即如果hashmap中的元素个数超过了总容量75%,则会触发扩容,扩容分为两个步骤:

  • 第1步 是对哈希表长度的扩展(2倍)
  • 第2步 是将旧哈希表中的数据放到新的哈希表中。
    因为我们使用的是2次幂的扩展(指长度扩为原来2倍),所以,元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。
    如我们从16扩展为32时,具体的变化如下所示:
    注意我这里
    h a s h 1 和 h a s h 2 hash_1和hash_2 hash1hash2只是任意举的例子,随便拿俩key出来举例,有一个例子是“原来索引的例子”,有一个是“原来索引位置+oldCap”的例子,你仔细看一眼n = 16 和n = 32的情况,
    在这里插入图片描述

在扩容过程中,树化要满足两个条件:

  1. 链表长度大于等于 TREEIFY_THRESHOLD(8)
  2. 桶数组容量大于等于 MIN_TREEIFY_CAPACITY (64)第一个条件比较好理解,这里就不说了。这里来说说加入第二个条件的原因,个人觉得原因如下:
    当桶数组容量比较小时,键值对节点 hash 的碰撞率可能会比较高,进而导致链表长度较长。这个时候应该优先扩容,而不是立马树化。毕竟高碰撞率是因为桶数组容量较小引起的,这个是主因。容量小时,优先扩容可以避免一些列的不必要的树化过程。同时,桶容量较小时,扩容会比较频繁,扩容时需要拆分红黑树并重新映射。所以在桶容量比较小的情况下,将长链表转成红黑树是一件吃力不讨好的事。

往hashmap存20个元素,会扩容几次?

当插入 20 个元素时,HashMap 的扩容过程如下
初始容量: 16
插入第 1到第 12 个元素时,不需要扩容。插入第 13 个元素时,达到负载因子限制,需要扩容。此时,HashMap 的容量从 16 扩容到 32。
扩容后的容量: 32
插入第 14 到第 24 个元素时,不需要扩容。
因此,总共会进行一次扩容。

说说hashmap的负载因子

HashMap 负载因子 loadFactor 的默认值是 0.75,当 HashMap 中的元素个数超过了容量的 75% 时,就会进行扩容。
默认负载因子为 0.75,是因为它提供了空间和时间复杂度之间的良好平衡。
负载因子太低会导致大量的空桶浪费空间,负载因子太高会导致大量的碰撞,降低性能。0.75 的负载因子在这两个因素之间取得了良好的平衡。

Hashmap和Hashtable有什么不一样的?

Hashmap一般怎么用?

  • HashMap线程不安全,效率高一点,可以存储nul的key和value:null的key只能有一个,null的value可以有多个。默认初始容量为16,每次扩充变为原来2倍。创建时如果给定了初始容量,则扩充为2的幂次方大小。底层数据结构为数组+链表,插入元素后如果链表长度大于阈值(默认为8),先判断数组长度是否小于64,如果小于,则扩充数组,反之将链表转化为红黑树,以减少搜索时间。
  • HashTable线程安全,效率低一点,其内部方法基本都经过synchronized修饰,不可以有null的key和value。默认初始容量为11,每次扩容变为原来的2n+1。创建时给定了初始容量,会直接用给定的大小。底层数据结构为数组+链表。它基本被淘汰了,要保证线程安全可以用ConcurrentHashMap。
  • 怎么用:HashMap主要用来存储键值对,可以调用put方法向其中加入元素,调用get方法获取某个键对应的值,也可以通过containsKey方法查看某个键是否存在等v

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

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

相关文章

【JavaEE】认识进程

一、操作系统(operating system) 操作系统是一组做计算机资源管理的软件的统称,它能够把一个计算机上的所有硬件资源和软件资源都管理好:能够管理好各种硬件资源,让他们很好的相互配合,能够管理好各种软件…

Android——横屏竖屏

系统配置变更的处理机制 为了避免横竖屏切换时重新加载界面的情况,Android设计了一中配置变更机制,在指定的环境配置发生变更之时,无需重启活动页面,只需执行特定的变更行为。该机制的视线过程分为两步: 修改 Androi…

基于卷积神经网络(CNN)的时间序列预测,15个输入1个输出,可以更改数据集,MATLAB代码

1. 数据收集与预处理 数据清洗:处理缺失值、异常值等。特征工程:提取有助于预测的特征。数据标准化:将时间序列数据标准化,使其具有零均值和单位方差,有助于模型训练。滑动窗口划分:将时间序列数据划分为多…

css 文字一行没有放满不进行换行

在开发过程中,经常会出现一行的文字没有放满 就出现了换行的情况 word-break: break-all;

社区团购 2.0 版本发展与创新模式研究:融合新元素的机遇与挑战

摘要:本文深入探讨了社区团购 2.0 版本的发展模式,以便利连锁店为核心的新形态对传统社区团购的冲击和革新。同时,分析了山东小爱联盟推动的爱客优选模式特点,包括佣金体系、运营模式等。在此基础上,研究如何将开源 AI…

isaac sim 14 物理学习(车辆动力学)

文章内容均来自博客文章、官方文档手册等 参考内容 Nvidia Isaac Sim代码编程 入门教程 2024(7)_isaac sim franka-CSDN博客 Python Bindings API — omni_physics 106.1 documentation Physics — Omniverse IsaacSim latest documentation Vehicle…

理解Laravel中的pipeline

pipeline在laravel的启动过程中出现次数很多,要了解laravel的启动过程和生命周期,理解pipeline就是其中的一个关键点。网上对pipeline的讲解很少,所以我自己写一写吧。 首先还是来看看调用栈,也就是从一个请求开始到返回响应&…

基于uniapp和java的电动车智能充电系统软件平台的设计

文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 对电动车智能充电系统进行设计和开发。通过使用本系统可有效地减少运营成本,提高管理效率。 根据近年来社会…

使用css和html制作导航栏

代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>*{margin: 0;padding: 0;}#m{background-color: antiquewhite;width: 100%;height: 50px;}#i{float: left;width: 100px;height: 50px;li…

怎样使用pycharm的服务?

‌在PyCharm中使用服务器的步骤如下‌&#xff1a; ‌打开PyCharm&#xff0c;选择“File”->“Settings”‌。‌选择左侧工具栏中的“Project:…”‌&#xff0c;然后选择“Python Interpreter”。‌点击右上角的“Add Interpreter”‌&#xff0c;选择“On SSH”。‌如果…

CI_CD

什么是CI/CD 在前端开发中&#xff0c;CI/CD 是 Continuous Integration&#xff08;持续集成&#xff09;和 Continuous Deployment/Continuous Delivery&#xff08;持续部署/持续交付&#xff09;的简称。它是一种软件开发实践&#xff0c;自动化了应用的构建、测试和发布过…

设置JAVA以适配华为2288HV2服务器的KVM控制台

华为2288HV2服务器比较老旧了&#xff0c;其管理控制台登录java配置比较麻烦&#xff0c;华为的ibmc_kvm_client_windows客户端测试了几个版本&#xff0c;连接控制台也有问题&#xff0c;最终安装JDK解决。 一、测试环境 主机为WindowsServer2012R2,64位系统 二、Java软件包…

机器学习—构建一个神经网络

如何在Tensorflow中构建神经网络&#xff1f; 回到之前的例子&#xff0c;如果你想做钱进支柱&#xff0c;初始化数据x创建第一层&#xff0c;如下图所示计算一个1&#xff0c;然后创建第二层并计算一个2&#xff0c;所以这是一种明确的向前推进的方式。 事实证明&#xff0c;…

基于51单片机的步进电机定时控制proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1_F5bfyS_e_eKSblnja7RqA 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

【云原生开发】如何通过client-go来操作K8S集群

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

idea 配置自动导入设置

配置自动导入设置&#xff1a; 通过访问 Settings→Editor→General→Auto Import&#xff0c;勾选 Add unambiguous imports on the fly 和 Optimize imports on the fly 选项&#xff0c;可以实现自动添加明确的导入和快速优化导入&#xff0c;即自动删除无用的导入

【文本情感分析识别】Python+SVM算法+模型训练+文本分类+文本情感分析

一、介绍 使用Python作为开发语言&#xff0c;基于文本数据集&#xff08;一个积极的xls文本格式和一个消极的xls文本格式文件&#xff09;&#xff0c;使用Word2vec对文本进行处理。通过支持向量机SVM算法训练情绪分类模型。实现对文本消极情感和文本积极情感的识别。并基于D…

iptables面试题

1、详述iptales工作流程以及规则过滤顺序&#xff1f; iptables过滤的规则顺序是由上至下&#xff0c;若出现相同的匹配规则则遵循由上至下的顺序 2、iptables的几个表以及每个表对应链的作用&#xff1f; Iptables有四表五链 Filter表 : Filter表是iptables中使用的默认表…

【青牛科技】GC2803:白色家电与安防领域中 ULN2803 的卓越替代者

在当今科技飞速发展的时代&#xff0c;电子元器件在各个领域都扮演着至关重要的角色。在白色家电和安防等产品的电路设计中&#xff0c;驱动芯片的选择尤为关键。传统的 ULN2803 曾是广泛应用的一款芯片&#xff0c;但如今&#xff0c;芯麦 GC2803 的出现为这些领域带来了新的选…

变脸、看完毒液3,我把自己的脸变毒液了,视频有点惊悚!请谨慎观看

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 AI工具集1&#xff1a;大厂AI工具【共23款…