哈希表与一致性哈希表

2023-05-16

哈希表定义

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。它通过把关键码映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数(哈希函数),存放记录的数组叫做散列表。

优缺点

哈希表可以提供快速的操作。第一次接触哈希表时,它的优点多得让人难以置信。不论哈希表中有多少数据,插入和删除只需要接近0(1)的时间级(由于碰撞冲突的存在,实际时间大于这个值)。在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)。哈希表的速度明显比树快,树的操作通常需要O(N)的时间级。哈希表不仅速度快,编程实现也相对容易。
当然,哈希表也有一些缺点。它通常是基于数组的,数组创建后难于扩展。所以哈希表被基本填满时,性能下降得非常严重,所以必须要清楚表中将要存储多少数据(或者准备好定期地把数据转移到更大的哈希表中,这是个费时的过程)。而且,也没有一种简便的方法可以以任何一种顺序〔例如从小到大)遍历表中的数据项。
综上,如果不需要有序遍历数据,井且可以提前预测数据量的大小。那么哈希表在速度和易用性方面是无与伦比的。

哈希查找

使用哈希查找有两个步骤:

1. 使用哈希函数将被查找的键转换为数组的索引。在理想的情况下,不同的键会被转换为不同的索引值,但是在有些情况下我们需要处理多个键被哈希到同一个索引值的情况。所以哈希查找的第二个步骤就是处理冲突。

2. 处理哈希碰撞冲突。有很多处理哈希碰撞冲突的方法,下文介绍。

哈希表是一个在时间和空间上作出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要根据实际情况,调整哈希函数即可在时间和空间上做出取舍。

哈希函数

在哈希表中,记录在表中的位置和其关键字之间存在着一种确定的关系。这样我们就能知道所查关键字在表中的位置,从而直接通过下标找到记录。

1.哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可;

2.由于哈希函数是一个压缩映象,因此,在一般情况下,很容易产生“冲突”现象,即: key1!=key2,而  f  (key1) = f(key2)。

3.只能尽量减少冲突而不能完全避免冲突,这是因为通常关键字集合比较大,其元素包括所有可能的关键字, 而地址集合的元素仅为哈希表中的地址值。在构造这种特殊的“查找表” 时,除了需要选择一个“好”(尽可能少产生冲突)的哈希函数之外;还需要找到一 种“处理冲突” 的方法。

哈希函数构造方法

散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位。一个好的散列函数一般应该考虑下列因素:

1.计算简单,以便提高转换速度。

2.关键词对应的地址空间分布均匀,以尽量减少冲突。

(当然也要考虑空间限制)

常见的哈希函数:

1.   直接寻址法

取关键字或者关键字的某个线性函数值作为哈希地址,即H(Key)=Key或者H(Key)=a*Key+b(a,b为整数),这种散列函数也叫做自身函数.如果H(Key)的哈希地址上已经有值了,那么就往下一个位置找,直到找到H(Key)的位置没有值了就把元素放进去。

例:有一个人口统计表,记录了从不同年龄的人口数目,其中年龄作为关键字,哈希函数取关键字本身。很显然,当需要查找某一年龄的人数时,直接查找相应的项即可。稍微复杂一点,如果我们要统计的是1990后出生的人口数,那么我们对出生年份这个关键字可以用年份减去1990来作为地址。这种哈希函数简单,并且对于不同的关键字不会产生冲突,但可以看出这是一种较为特殊的哈希函数,实际生活中,关键字的元素很少是连续的。用该方法产生的哈希表会造成空间大量的浪费,因此这种方法适应性并不强。


2.   数字分析法

分析一组数据,比如一组员工的出生年月,这时我们发现出生年月的前几位数字一般都相同,因此,出现冲突的概率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果利用后面的几位数字来构造散列地址,则冲突的几率则会明显降低.因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。这就要求能预先估计出全体关键字的每一位上各种数字出现的频度。


3.   平方取中法

取关键字平方后的中间几位作为散列地址。因为这种方法的原理是通过取平方扩大差别,平方值的中间几位和这个数的每一位都相关,则对不同的关键字得到的哈希函数值不易产生冲突,由此产生的哈希地址也较为均匀该方法适用于关键字中的每一位都有某些数字重复出现频度很高的现象。


4.   折叠法

折叠法是将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(注意:叠加和时去除进位)作为散列地址.数位叠加可以有移位叠加和间界叠加两种方法.移位叠加是将分割后的每一部分的最低位对齐,然后相加;间界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加。该方法适用于关键字特别多的情况。


5.   随机数法

选择一个随机数,作为散列地址,通常用于关键字长度不同的场合。此时,H(key)=random(key)。

6.   除留余数法

取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址.即H(Key)=Key MOD p,p<=m.不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选得不好,则很容易产生冲突。


实际造表时,采用何种构造哈希函数的方法取决于很多因素。另外,哈希函数也远远不止上面的这几种,只要合理考虑下面这几个因素的,理论上都可以作为哈希函数:

l 计算哈希函数所需时间 (简单)。

l 关键字的长度。

l 哈希表大小。

l 关键分布情况。

l 记录查找频率

哈希冲突

通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题。创建哈希表和查找哈希表都会遇到冲突,两种情况下解决冲突的方法应该一致。下面以创建哈希表为例,说明解决冲突的方法。

1.开放定址法

这种方法也称再散列法,其基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。这种方法有一个通用的再散列函数形式:Hi=(H(key)+di)%m   i=1,2,…,m-1,其中H(key)为哈希函数,m 为表长,di称为增量序列,i为碰撞次数。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下几种:

(1) 线性探测再散列

di=1,2,3,…,m-1

这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。

(2)二次探测再散列

 di=12-1222-22k2-k2    ( k<=m/2 )

这种方法的特点是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。

(3)伪随机探测再散列

di=伪随机数序列。

在实际程序中应预先用随机数发生器产生一个随机序列,将此序列作为依次探测的步长。这样就能使不同的关键字具有不同的探测次序,从而可以避免或减少聚集。

线性探测再散列的优点是:只要哈希表不满,就一定能找到一个不冲突的哈希地址,而二次探测再散列和伪随机探测再散列则不一定。线性探测再散列容易产生“二次聚集”,即在处理同义词的冲突时又导致非同义词的冲突。

其实除了上面的几种方法,开放定址法还有很多变种,不过都是对di有不同的表示方法。(如双散列探测法:di=i*h2(k))

2.再哈希法

这种方法是同时构造多个不同的哈希函数:Hi=RHi(key),i=1,2,3,…,n。

当哈希地址H1=RH1(key)发生冲突时,再计算H2=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。 

 3.链地址法(拉链法)

这种方法的基本思想是将所有哈希地址相同的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表中,因而查找、插入和删除主要在同义词链中进行。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。链地址法适用于经常进行插入和删除的情况。

拉链法的优点

与开放定址法相比,拉链法有如下几个优点:

(1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短; 

(2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;

(3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中理论上可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;(散列表的装填因子定义为:α= 填入表中的元素个数 / 散列表的长度)

注:HashMap默认装填因子是0.75。

(4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放定址法构造的散列表,删除结点不能简单地将被删结点的空间置为空,否则将截断在它之后填入散列表的同义词结点的查找路径。这是因为各种开放定址法中,空地址单元都被理解没有查找到元素。 因此在用开放定址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。

拉链法的缺点

拉链法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,此时将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。

4、建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表(在这个方法里面是把元素分开两个表来存储)。

Java中的equals和hashCode

首先,Java中equals方法和hashCode方法都是Object类中就有的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法。Object类中,equals其实就是比较地址是否相等,而hashCode就是散列函数的实现,是native方法,实现逻辑与JVM有关,有些JVM是直接返回对象的存储地址,但是大多时候并不是这样,只能说可能和存储地址有一定关联。equals和hashCode共同作用,有效支撑了基于哈希机制的集合类。

由于两者经常被重写,这里说一些重写的原则。

equals重写约定

自反性:  x.equals(x) 一定是true。

对null:  x.equals(null) 一定是false。

对称性:  x.equals(y)和y.equals(x)结果一致。

传递性:x.equals(y), 并且y.equals(z),那么x.equals(z)。

一致性:对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)返回结果一致;因此,equals方法里面不应该依赖任何不可靠的资源。

hashCode重写约定

在某个运行时期间,只要对象的变化不会影响equals方法的决策结果,那么,在这个期间,无论调用多少次hashCode,都必须返回同一个散列码。

通过equals调用返回true的2个对象的hashCode一定一样。

通过equasl返回false的2个对象的散列码不需要不同,也就是他们的hashCode方法的返回值允许出现相同的情况。

总结一句话:等价的(调用equals返回true)对象必须产生相同的散列码。不等价的对象,不要求产生的散列码不相同。

注:关于hashCode的约定,参考哈希表的定义,就变得很好理解。因为要同时兼顾时间空间,所以允许一定的哈希冲突,但必须保证等价对象的哈希值相等(当然哈希函数还是要尽量减少冲突的)。

为了更好地遵从上面的约定,可以如此规范:重写了euqls方法的对象必须同时重写hashCode方法。

哈希加密算法

现代通常所说的哈希算法,应该区别于哈希表的构造函数算法(因为哈希算法在此基础上增加了额外的含义),并广泛用于密码学等领域。

密码学里面有一类算法叫做哈希哈希算法,也称作散列算法、摘要算法,通常用于对一段信息的取样。当你给它一段信息(message)时,可以用特定算法生成一段信息摘要(message digest),通常摘要的长度更短。摘要(digest)可以表示这段信息的某种特征——就如同指纹一样,所以这个特征也叫做指纹(fingerprint)、校验。

理想情况下,哈希算法应该有四个重要特性(这里是密码学中的哈希算法):

不可逆:不能从摘要生成其原始信息

无冲突:不同的信息具备不同的摘要

易计算:对任意信息容易计算其摘要

特征化:信息修改后其摘要一定变化

实际上,前两个特性基本无法绝对实现。以流行的MD5举例,既无法避免彩虹表的存在,也早在2004年就实现了碰撞。截至2015年,这些算法的生存状况如图:


一致性哈希

一致性哈希算法(consistent hashing) ,主要用于发布式缓存中。在一些高速发展的web系统中,传统的哈希函数,如hash取模法,存在明显缺陷。随着系统访问压力的增长,缓存系统不得不通过增加机器节点的方式提高集群的相应速度和数据承载量。增加机器意味着,如果按照hash取模的方式,在增加机器节点的这一时刻,大量的缓存不能命中,缓存数据需要重新建立,甚至是整体迁移,这一瞬间会给DB带来极高的系统负载。

判定哈希算法好坏的四个定义:

1、平衡性(Balance):平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。很多哈希算法都能够满足这一条件。

2、单调性(Monotonicity):单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。

3、分散性(Spread):在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。

4、负载(Load):负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。

在分布式集群中,对机器的添加删除,或者机器故障后自动脱离集群这些操作是分布式集群管理最基本的功能。如果采用常用的hash取模算法,那么在有机器添加或者删除后,很多原有的数据就无法找到了,这样严重的违反了单调性原则。接下来主要说明一下一致性哈希算法是如何设计的。

以SpyMemcached的ketama算法来说,思路是这样的:

环形Hash空间
按照一定的hash算法来将对应的key哈希到一个具有2^32个桶的空间中,即0~(2^32)-1的数字空间中。现在我们可以将这些数字头尾相连,想象成一个闭合的环形。
                                                                        
把数据通过一定的hash算法处理后映射到环上
现在我们将object1、object2、object3、object4四个对象通过特定的Hash函数计算出对应的key值,然后散列到Hash环上。
[plain]  view plain  copy
  1. Hash(object1) = key1;  
  2. Hash(object2) = key2;  
  3. Hash(object3) = key3;  
  4. Hash(object4) = key4;  
                                                          
将机器通过hash算法映射到环上
通过使用与对象存储一样的Hash算法将机器也映射到环中(一般情况下对机器的hash计算是采用机器的IP或者机器唯一的别名作为输入值),然后以 顺时针的方向计算,将所有对象存储到离自己最近的机器中。假设现在有NODE1,NODE2,NODE3三台机器,通过Hash算法得到对应的KEY值,映射到环中。
[plain]  view plain  copy
  1. Hash(NODE1) = KEY1;  
  2. Hash(NODE2) = KEY2;  
  3. Hash(NODE3) = KEY3;  
                                                            
通过上图可以看出对象与机器处于同一哈希空间中,这样按顺时针转动object1存储到了NODE1中,object3存储到了NODE2中,object2、object4存储到了NODE3中。在这样的部署环境中,hash环是不会变更的,因此,通过算出对象的hash值就能快速的定位到对应的机器中,这样就能找到对象真正的存储位置了。

机器的删除与添加
普通hash求余算法最为不妥的地方就是在有机器的添加或者删除之后会照成大量的对象存储位置失效,这样就大大的不满足单调性了。下面来分析一下一致性哈希算法是如何处理的。
1. 节点(机器)的删除
以上面的分布为例,如果NODE2出现故障被删除了,那么按照顺时针迁移的方法,object3将会被迁移到NODE3中,这样仅仅是object3的映射位置发生了变化,其它的对象没有任何的改动。如下图:
                                                             
2. 节点(机器)的添加 
如果往集群中添加一个新的节点NODE4,通过对应的哈希算法得到KEY4,并映射到环中,如下图:
                                                             
    通过按顺时针迁移的规则,那么object2被迁移到了NODE4中,其它对象还保持这原有的存储位置。通过对节点的添加和删除的分析,一致性哈希算法在保持了单调性的同时,还是数据的迁移达到了最小,这样的算法对分布式集群来说是非常合适的,避免了大量数据迁移,减小了服务器的的压力。

平衡性
根据上面的图解分析,一致性哈希算法满足了单调性和负载均衡的特性以及一般hash算法的分散性,但这还并不能当做其被广泛应用的原由,因为还缺少了平衡性。下面将分析一致性哈希算法是如何满足平衡性的。hash算法本身是不保证平衡的,如上面只部署了NODE1和NODE3的情况(NODE2被删除的图),object1存储到了NODE1中,而object2、object3、object4都存储到了NODE3中,这样就照成了非常不平衡的状态。在一致性哈希算法中,为了尽可能的满足平衡性,其引入了虚拟节点。
“虚拟节点”( virtual node )是实际节点(机器)在 hash 空间的复制品( replica ),实际个节点(机器)对应了若干个“虚拟节点”,这个对应个数也成为“复制个数”,“虚拟节点”在 hash 空间中以hash值排列。
用上文只部署了NODE1和NODE3的情况(NODE2被删除的图)为例,之前的对象在机器上的分布很不均衡,现在我们以2个副本(复制个数)为例,这样整个hash环中就存在了4个虚拟节点,最后对象映射的关系图如下:
                                                                
根据上图可知对象的映射关系:object1->NODE1-1,object2->NODE1-2,object3->NODE3-2,object4->NODE3-1。通过虚拟节点的引入,对象的分布就比较均衡了。那么在实际操作中,真正的对象查询是如何工作的呢?对象从hash到虚拟节点到实际节点的转换如下图:
                                        
“虚拟节点”的hash计算可以采用对应节点的IP地址加数字后缀的方式。例如假设NODE1的IP地址为192.168.1.100。引入“虚拟节点”前,计算 cacheA的hash值:
[plain]  view plain  copy
  1. Hash(“192.168.1.100”);  
引入“虚拟节点”后,计算“虚拟节”点NODE1-1和NODE1-2的hash值:
[plain]  view plain  copy
  1. Hash(“192.168.1.100#1”); // NODE1-1  
  2. Hash(“192.168.1.100#2”); // NODE1-2  

使用虚拟节点的思想,为每个物理节点(服务器)在分配100~200个虚拟节点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。用户数据映射在虚拟节点上,就表示用户数据真正存储位置是在该虚拟节点代表的实际物理服务器上。
下图描述了需要为每台物理服务器增加的虚拟节点。x轴表示的是需要为每台物理服务器扩展的虚拟节点倍数,y轴是实际物理服务器数。可以看出,当物理服务器的数量很小时,需要更大的虚拟节点,反之则需要更少的节点,从图上可以看出,在物理服务器有10台时,差不多需要为每台服务器增加100~200个虚拟节点才能达到真正的负载均衡。


参考地址:http://baike.baidu.com/

参考地址:http://blog.csdn.net/tanggao1314/article/details/51457585

参考地址:http://blog.csdn.net/qq_21688757/article/details/53861896

参考地址:http://www.linuxidc.com/Linux/2016-01/127239.htm

参考地址:http://blog.csdn.net/cywosp/article/details/23397179

参考地址:http://blog.csdn.net/kongqz/article/details/6695417

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

哈希表与一致性哈希表 的相关文章

随机推荐

  • XGBoost之类别特征的处理

    目录 Label encoding与 One Hot encoding Label encoding one hot encoding 利用神经网络的Embedding层处理类别特征 Embedding简介 Network Embeddin
  • window10系统英伟达NVIDIA显卡驱动和CUDA软件的安装和升级

    目录 一 如何查看电脑是否支持CUDA及支持的CUDA版本 二 如何知道我的显卡是否支持CUDA加速 三 查看显卡是否支持CUDA及支持的版本 四 英伟达NVIDIA显卡驱动下载与安装和升级 如下方案亲测试可用 一 如何查看电脑是否支持CU
  • Pytorch替换model对象任意层的方法

    Pytorch替换model对象任意层的方法 知乎 直接上代码 import torch from torch import nn from torchvision models import alexnet 核心函数 xff0c 参考了t
  • Keras打印tensor的值以及学习率

    keras 打印 tensor 的值 小又欠的博客 CSDN博客 keras查看tensor的值 keras 打印 tensor 的值在调试时 xff0c 此问题困扰我许久网上大多都是 sess run xff0c 且也是 tensorfl
  • 一种基于目标检测实现黑花屏分类任务的方案

    转载 xff1a 一种基于目标检测实现黑花屏分类任务的方案 视频花屏检测 叶赫那拉 赫敏的博客 CSDN博客 然而 xff0c 在项目过程中 xff0c 视频帧数据的收集比较困难 xff0c 数据量较少 xff0c 部分花屏和正常屏之间差异
  • 开源工业缺陷数据集汇总,持续更新中(已更新28个)

    转载 xff1a 开源工业缺陷数据集汇总 xff0c 持续更新中 xff08 已更新28个 xff09 知乎 欢迎大家关注我的公众号 xff1a 一刻AI 本文目前汇总了常见的28个开源工业缺陷数据集 xff0c 持续更新中 xff08 欢
  • 带你了解ICCV、ECCV、CVPR三大国际会议

    文章目录 前言 一 ICCV ECCV CVPR是什么 1 ICCV 2 ECCV 3 CVPR 二 三大会链接及论文下载链接 前言 作为刚入门CV的新人 有必要记住计算机视觉方面的三大顶级会议 ICCV CVPR ECCV 统称为ICE
  • 深度学习之卷积神经网络CNN详解

    TensorFlow 卷积层 池化层详解 叠加态的猫 博客园 两种网络层实现的数学细节 https www cnblogs com hellcat p 7850048 html 一 CNN概述 CNN一个牛逼的地方就在于通过感受野和权值共享
  • 深度学习之卷积神经网络CNN 常用的几个模型

    LeNet5 论文 xff1a http yann lecun com exdb publis pdf lecun 01a pdf LeNet 5 xff1a 是Yann LeCun在1998年设计的用于手写数字识别的卷积神经网络 xff0
  • AI Stable Diffusion Prompt参数【二】之 生成效果查验

    AI Stable Diffusion Prompt参数 二 之 生成效果查验 效果国漫风生成参数配置prompt xff1a Negative prompt Model Steps Sampler CFG scale Clip skip
  • batch norm、relu、dropout 等的相对顺序和BN、dropout的几个问题和思考

    总结 xff1a BN和dropout一般不同时使用 xff0c 如果一定要同时使用 xff0c 可以将dropout放置于BN后面 1 batch norm relu dropout 等的相对顺序 Ordering of batch no
  • 推荐系统之ESMM算法精读和实战

    目录 一 背景 二 ESMM模型 2 1 ESMM 模型结构 2 2 ESMM模型特点 2 3 ESMM模型适用场景 三 实验效果 lt
  • 远程桌面连接 提示用户名密码错误的解决办法

    提示 用户名或者密码错误 xff0c 有两种可能 xff1a 1是 用户名 密码可能输入错误 2是 可能你这个用户名暂不支持远程访问 首先解决用户名 密码的问题 xff1a 计算机的命名规则为 计算机 43 账户 的形式 如果您的账户不是A
  • 金融时间序列模型整理

    GARCH模型 https www math pku edu cn teachers lidf course fts ftsnotes html ftsnotes fts garch html 金融时间序列入门 完结篇 ARCH GARCH
  • 工具学习——ubuntu轻量桌面对比

    因为最近要做一些ubuntu上的开发 xff0c 然后使用ssh问题是经常会出现中断 xff0c 虽然可以使用等tmux方法来挂起进程 xff0c 但是感觉不如界面方便 xff0c 然后现在问题来了 xff0c 我的ubuntu服务器是一个
  • JPA自定义VO接受返回结果集(unwrap)

    JPA跟mybitis比较 xff0c 简单的业务搜索是方便的 xff0c 但是设计到复杂的SQL搜索时 xff0c 我们需要自定义SQL 1 64 Query直接写SQL 缺点是无法动态的组装条件 2 JPA的Specification对
  • 快速排序详解-java实现

    一 快速排序 整体过程 xff1a 1 先从数组中找一个数作为基准数 xff0c 2 进行分区 xff0c 分区时大于这个数得全部放到右边 xff0c 小于这个数得全部放到左边 xff0c 等于这个数得全部放到中间 xff08 核心过程 x
  • 应届生应该如何准备校招

    大家好 xff0c 我是羽峰 xff0c 今天要和大家分享的是应届生应该如何准备校招 xff0c 希望该文章对一些今年要找工作的朋友有一些帮助 还是老话 xff0c 我是羽峰 xff0c 希望我所分享的文章能为您及更多的朋友带来帮助 欢迎转
  • mysql提示Can‘t connect to MySQL server on localhost (10061)解决方法

    本文mysql的安装环境为win10 64位 xff0c mysql版本为MySQL5 7 我遇到的问题是 电脑原先安装过mysql xff0c 卸载不干净 xff0c 重装默认以前的用户名和密码 xff0c 然鹅 我不知道用户名和密码 以
  • 哈希表与一致性哈希表

    哈希表定义 散列表 xff08 Hash table xff0c 也叫哈希表 xff09 xff0c 是根据关键码值 Key value 而直接进行访问的数据结构 它通过把关键码映射到表中一个位置来访问记录 xff0c 以加快查找的速度 这