散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。 我用一个例子来解释一下。假如我们有 89 名选手参加学校运动会。...我们把参赛编号转化为数组下标的映射方法就叫作散列函数(或“Hash 函数”“哈希函数”),而散列函数计算得到的值就叫作散列值(或“Hash 值”“哈希值”)。...刚刚举的学校运动会的例子,散列函数比较简单,也比较容易想到。但是,如果参赛选手的编号是随机生成的 6 位数字,又或者用的是 a 到 z 之间的字符串,该如何构造散列函数呢?...我们来看这个图,在散列表中,每个“桶(bucket)”或者“槽(slot)”会对应一条链表,所有散列值相同的元素我们都放到相同槽位对应的链表中。...有两个字符串数组,每个数组大约有 10 万条字符串,如何快速找出两个数组中相同的字符串?
MD5 可以将任意字符串,通过不可逆的字符串变换算法,生成一个唯一的 MD5 信息摘要,这个信息摘要也就是我们通常所说的 MD5 字符串。那么问题来了,MD5 加密安全吗?...彩虹表是一个用于加密散列函数逆运算的预先计算好的表, 为破解密码的散列值(或称哈希值、微缩图、摘要、指纹、哈希密文)而准备。 一般主流的彩虹表都在 100G 以上。...这是空间/时间替换的典型实践,比每一次尝试都计算哈希的暴力破解处理时间少而储存空间多,但却比简单的对每条输入散列翻查表的破解方式储存空间少而处理时间多。...盐(Salt):在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为“加盐”。...MD5 加密是不安全的,因为每个字符串都会生成固定的密文,那么我们就可以使用彩虹表将密文还原出来,所以它不是安全的。
一个调皮的读者在之前我写的“我去”系列文章里留言调侃说,“二哥,你是无中生小王吗?”不不不,其实真不是的,小王是真实存在的,他一直和我并肩作战,不辞辛劳,让我既爱又恨。...我爱他,因为他兢兢业业,任劳任怨,和我心有灵犀;我恨他,因为他时不时会中二一下,问我一些可笑的问题,比如说这次,“二哥,你能给我说说 Java 如何生成 UUID 吗?”...每一部分都是一个十六进制的数字,注意并不是随机的任意字母+数字的字符串。 M 表示 UUID 的版本,N 为 UUID 的变体(Variants)。...作为散列算法)名字空间(namespace)标识符和名称生成的; 版本 4 - UUID 使用随机性或伪随机性生成; 版本 5 类似于版本 3(SHA1 作为散列算法)。...所以 Java 的 UUID 通常可用于以下地方: 随机生成的文件名; Java Web 应用程序的 sessionID; 数据库表的主键; 事务 ID(UUID 生成算法非常高效,每台计算机每秒高达
得到的两串毫无规律的字符串(MD5的哈希值是128位的Bit长度,便于表示,转化为16进制编码)。可以看出,无论文本的长度是多少,得到的哈希值长度是相同的,而且看起来像一堆随机数,完全没有规律。...如果还想继续提高效率,我们可以把每个图片的唯一标识,和相应的图片文件在图库中的路径信息,都存储在散列表中。...长期以来,人们都认为SHA1是十分安全的,至少大家还没有找到一次碰撞案例。08.云存储文件场景现在大部分的网络部署和版本控制工具都在使用散列算法来保证文件可靠性。...String类的hashCode. 根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串的内容相同,返回的哈希码也相同。...用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术(线性探测法、二次探测法(解决线性探测的堆积问题)、随机探测法(和二次探测原理一致,不一样的是:二次探测以定值跳跃,而随机探测的散列地址跳跃长度是不定值
至此我们可以发现,字典法不就是散列链集当k等于1时的特殊情况吗?...如果每个用户都用一个不同的盐值,那么每个用户的H函数都不同,则必须要为每个用户都生成一个不同的彩虹表,这就大大提高了破解难度(参考博客6、7、8等)。对此我不以为然。 ...此时,尽管这两个用户使用的是同一个明文密码,但由于这两个用户并非同一个用户,因而我们的网站系统会给这两个用户的明文密码加上不同的随机字符串。...这里再总结一下:如果每个用户都用一个不同的盐值,必须要为每个用户都生成一个不同的彩虹表,这就大大提高了破解难度。从这句话可以看出,加盐可以让攻击者无法使用查表和彩虹表的方式对大量hash进行破解。...对于拒绝服务攻击可以通过让用户登陆的时候输入验证码的方式来防御。系统设计的时候一定要考虑到这个迭代次数将来可以方便的增加或降低。
我们把所有的价格都背下来不就可以了吗?每个菜的价格我们都了如指掌,结账的时候我们只需把每道菜的价格相加即可。所以袁厨和老板娘加班加点的进行背诵。下次再结账的时候一说吃了什么菜,我们立马就知道价格啦。...但是我们需要注意的是,无论什么记录我们都需要用同一个散列函数计算地址,然后再存储。 (2)当我们查找时,我们通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。...(具体解析见随机探测法) 适用场景:关键字的长度不等时 上面我们的例子都是通过数字进行举例,那么如果是字符串可不可以作为键呢?...所以为什么我们可以使用随机数作为它的偏移量。 下面我们再来看一下其他的函数处理散列冲突的方法 再哈希法 这个方法其实也特别简单,利用不同的哈希函数再求得一个哈希地址,直到不出现冲突为止。...上面的情景就是模拟我们的公共溢出区法,这也是很好理解的,你不是冲突吗?那冲突的各位我先给你安排个地方呆着,这样你就有地方住了。我们为所有冲突的关键字建立了一个公共的溢出区来存放。
我们把所有的价格都背下来不就可以了吗?每个菜的价格我们都了如指掌,结账的时候我们只需把每道菜的价格相加即可。所以袁厨和老板娘加班加点的进行背诵。下次再结账的时候一说吃了什么菜,我们立马就知道价格啦。...但是我们需要注意的是,无论什么记录我们都需要用同一个散列函数计算地址,然后再存储。 (2)当我们查找时,我们通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。...(具体解析见随机探测法) 适用场景:关键字的长度不等时 上面我们的例子都是通过数字进行举例,那么如果是字符串可不可以作为键呢?...所以为什么我们可以使用随机数作为它的偏移量。 下面我们再来看一下其他的函数处理散列冲突的方法 再哈希法 这个方法其实也特别简单,利用不同的哈希函数再求得一个哈希地址,直到不出现冲突为止。...上面的情景就是模拟我们的公共溢出区法,这也是很好理解的,你不是冲突吗?那冲突的各位我先给你安排个地方呆着,这样你就有地方住了。我们为所有冲突的关键字建立了一个公共的溢出区来存放。 ?
一、前言 得益于Doug Lea老爷子的操刀,让HashMap成为使用和面试最频繁的API,没办法设计的太优秀了! HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现。...方案: 如果说我们需要通过ID从数组中获取元素,那么就需要把每个字符串都计算出一个在数组中的位置ID。字符串获取ID你能想到什么方式?...计算方式如下图; [bugstack.cn 扰动函数] 说白了,使用扰动函数就是为了增加随机性,让数据元素更加均衡的散列,减少碰撞。...2.2 实验验证扰动函数 从上面的分析可以看出,扰动函数使用了哈希值的高半区和低半区做异或,混合原始哈希码的高位和低位,以此来加大低位区的随机性。...对我个人来说以前也知道这部分知识,但是没有验证过,只知道概念如此,正好借着写面试手册专栏,加深学习,用数据验证理论,让知识点可以更加深入的理解。
这篇文章主要介绍自定义类的一些特殊方法,来让类的行为跟真正的 Python 对象一样。 类的特殊方法 类的特殊方法是为了被解释器调用,目的是可以将一些内置的方法用在对象上。...比如特殊方法 __len__ 是为了 len() 函数的调用,我们在使用的时候就可以直接使用 len(a) 这种写法,而不是 a....在类中,我们需要实现 __repr__ 或 __str__ 方法来实现将对象用字符串表示。需要注意的是, __repr__ 所返回的字符串应该准确无歧义。....: In [2]: format(Test(123, 9), "d") Out[2]: '123.9' 类的散列化 为了实现类的散列化,我们需要实现 __hash__ 方法。...这个方法需要返回一个整数,且需要保证相等对象的散列值相同,所以最好的实现方式是使用异或运算来混合各属性的散列值。
我们基于一种结果尽可能随机平均分布的固定函数H为每个元素安排存储位置,这样就可以避免遍历性的线性搜索,以达到快速存取。但是由于此随机性,也必然导致一个问题就是冲突。...常用的构造散列函数的方法 散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位: 1. 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。...随机数法:选择一随机函数,取关键字的随机值作为散列地址,通常用于关键字长度不同的场合。 6. 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。...散列法当然不止一种,下面列出三种比较常用的: 1,除法散列法 最直观的一种,上图使用的就是这种散列法,公式: index = value % 16 学过汇编的都知道,求模数其实是通过一个除法运算得到的...解决该问题的方法很多,我首先想到的就是用“链表”,感谢大学里学的数据结构教会了这个百试百灵的法宝,我遇到的很多算法都可以转化成链表来解决,只要在哈希表的每个入口挂一个链表,保存所有对应的字符串就OK了。
方案:如果说我们需要通过ID从数组中获取元素,那么就需要把每个字符串都计算出一个在数组中的位置ID。字符串获取ID你能想到什么方式?...这里所有的元素存放都需要获取一个索引位置,而如果元素的位置不够散列碰撞严重,那么就失去了散列表存放的意义,没有达到预期的性能。...计算方式如下图; bugstack.cn 扰动函数 说白了,使用扰动函数就是为了增加随机性,让数据元素更加均衡的散列,减少碰撞。...2.2 实验验证扰动函数 从上面的分析可以看出,扰动函数使用了哈希值的高半区和低半区做异或,混合原始哈希码的高位和低位,以此来加大低位区的随机性。...对我个人来说以前也知道这部分知识,但是没有验证过,只知道概念如此,正好借着写面试手册专栏,加深学习,用数据验证理论,让知识点可以更加深入的理解。
这是以空间换时间的典型实践,在每一次尝试都计算的暴力破解中使用更少的计算能力和更多的储存空间,但却比简单的每个输入一条散列的翻查表使用更少的储存空间和更多的计算性能。 ?...加盐Hash算法 盐(Salt),在密码学中,是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。...其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情景中,这个处理可以增加额外的安全性。...加盐后的散列值,可以极大的降低由于用户数据被盗而带来的密码泄漏风险,即使通过彩虹表寻找到了散列后的数值所对应的原始内容,但是由于经过了加盐,插入的字符串扰乱了真正的密码,使得获得真实密码的概率大大降低。...Java中使用scrypt 有一个Java实现的scrypt工具类库(https://github.com/wg/scrypt )可以直接使用。
关于散列表的代码实现及下边实践部分的代码实现均可从我的Github获取(欢迎star^_^) 散列思想 概念 散列表(Hash Table),也可以叫它哈希表或者Hash表 散列表用的是数组支持按照下标随机访问数据的特性...可以说,如果没有数组,就没有散列表 举例 假设全校有1000名学生,为了方便记录他们的期末成绩,会给每个学生一个编号,编号从1~1000。...但是,如果学生的编号是随机生成的6位数字,又或者用的是a到z之间的字符串,这种情况,散列函数就会复杂一些 散列函数设计的基本要求 散列函数计算得到的散列值是一个非负整数 如果key1 = key2,那hash...在散列表中,每个“桶(bucket)”或者“槽(slot)”会对应一条链表,所有散列值相同的元素都放到相同槽位对应的链表中 [46506618f3cc417facd93ecbfc8fe86d~tplv-k3u1fbpfcp-watermark.image...如果 K 非常大(比如大于10万),就使用快速排序,复杂度O(NlogN) 由于文章篇幅的原因,代码实现,我放在了github上,需要的可以自取(GO实现) 有两个字符串数组,每个数组大约有10万条字符串
1 什么是散列? 散列表,Hash Table,用数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。 假如有89名候选人参加大选。...为了方便记录投票,每个候选人胸前会贴上自己的参赛号码。这89名选手的编号依次是1到89。 通过编号快速找到对应的选手信息。你怎么做?...N位数或a到z之间的字符串,散列函数该如何实现?...不能太复杂 过度复杂会消耗大量计算时间,影响hash表性能 hash函数生成的值要尽可能随机并且均匀分布 避免或最小化哈希冲突,而且即便出现冲突,散列到每个槽里的数据也会比较平均,不会数据倾斜 2.2...4.散列函数 散列函数的设计并不复杂,追求的是简单高效、分布均匀。我把它摘抄出来,你可以看看。
1 什么是散列? 散列表,Hash Table,用数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。 假如有89名候选人参加大选。...N位数或a到z之间的字符串,散列函数该如何实现?...不能太复杂 过度复杂会消耗大量计算时间,影响hash表性能 hash函数生成的值要尽可能随机并且均匀分布 避免或最小化哈希冲突,而且即便出现冲突,散列到每个槽里的数据也会比较平均,不会数据倾斜 2.2...散列表中,每个“桶(bucket)”或“槽(slot)”对应一条链表:散列值相同的元素放到相同槽位对应的链表。...4.散列函数 散列函数的设计并不复杂,追求的是简单高效、分布均匀。我把它摘抄出来,你可以看看。
例如: 1、优化散列算法,提高散列值随机性: 将散列值尽可能均匀分布到输出值域的范围内,避免出现 “堆积” 线程。否则,当大部分散列值都堆积在一小块区域上时,势必会增大冲突概率。...我分为 3 点来回答: 第 1 点:HashMap 的定义是一个散列表,这是一种支持快速查找元素的数据结构,那么其背后就必然会使用到数组随机访问的特点。...我认为 Java 给予 HashMap 的定位是一个相对通用的散列表容器,它应该在面对各种输入的时候都表现稳定。...这个问题我认为有 2 个原因: 1、不可变类 String 可以避免修改后无法定位键值对: 假设 String 是可变类,当我们在 HashMap 中构建起一个以 String 为 Key 的键值对时,...而不可变类可以规避这个问题。
如果我们编写一个返回 0 到 7 范围内的数字的哈希函数,并为其提供 9 个唯一输入,则可以保证至少发生 1 次冲突。 为了可视化碰撞,我将使用网格。网格的每个方块将代表哈希函数输出的数字。...让我们采用一个更大的网格并对 1,000 个随机生成的字符串进行哈希处理。您可以单击网格来对一组新的随机输入进行散列,网格将以动画方式向您显示每个输入被散列并放置在网格上。...然后,它使用模运算符 (%) 确保该值介于 0 和 1000000 之间。我们将此哈希函数称为 stringSum。 这是在网格上。提醒一下,这是我们正在散列的 1,000 个随机生成的字符串。...问题是我们要进行哈希处理的字符串是随机的。让我们看看当给定的输入不是随机的时每个函数如何执行:从 1 到 1000 的数字转换为字符串。 现在问题更加清楚了。...为什么所有这些乱码字符串都会散列到相同的数字? 我对 141 万亿个随机字符串进行哈希处理,以找到在使用 murmur3 时哈希到数字 1228476406 的值。
本文中,我将使用比特币作为“区块链”的例子,但本文描述的大多数概念都适用于其他加密货币。...[2] 比特币使用称为SHA-256的哈希加密算法, SHA-256应用于块数据(比特币交易)和一个称为nonce的随机数组合,通过更改块数据或随机数,我们可以得到完全不同的散列值。...我们可以通过使条件更复杂来增加"挖矿”的复杂性,例如我们可以增加散列值开始所需的0的数量。 矿工需要找到一个随机数值,使得散列值满足“开采”条件。...你可以使用下面的应用程序来模拟有3个区块的区块链。当你输入“Data”文本框或更改nonce值时,可以注意到下一个块的散列值和“Prev”值(前一个散列)的更改。...您可以通过单击每个块的“开采”按钮来模拟采矿过程。在挖出3个区块之后,尝试更改块1或块2中的数据,并且您会注意到后面的所有块都变为无效。
//hand of it }finally{ //must be run} try、catch、finally三个语句块可能会涉及以下考题: 1)try、catch、finally可以单独使用吗...这个方面的知识点通常都是以一个非常具体的随机性的题目呈现,考题范围重点包括字符串的处理、日期函数的运用、正则表达式的运用、Java的集合。...它们之间的区别在于容器内每个“槽”所存储的元素个数不同,Collection每个槽内只能存储一个元素,而Map类型中,每个槽内存储key-value关联。Java容器类都可以自动调整自己的尺寸。...|--LinkedList:插入、删除、移动元素方便,但随机访问元素差② --Set:每个值只能保存一个对象,不能包含重复的元素 |--HashSet:使用散列函数 |--TreeSet...:使用红黑树 |--LinkedHashSet:使用链表结合散列函数③ --Queue:先进先出的容器Map的子类:① --HashMap:使用散列函数② --HashTable:使用散列函数③
领取专属 10元无门槛券
手把手带您无忧上云