hash函数

HashMap源码分析

一个人想着一个人 提交于 2020-02-06 17:12:08
概述 HashMap实现了Map<K, V>接口,通过键-值(key-value)的方式存取数据。内部的数据结构是数组+链表(或者Tree),插入时通过key的hash值,映射((n - 1) & hash,其中n为数组的长度)到数组中的位置,如果hash值重复,则在链表的末端插入(当一个链表中的数据大于等于8个时,就将链表转变为Tree),而当数组达到一定值时,会resize,重新创建一个数组,大小是之前的两倍;取出时,也是通过key的hash值,映射到数组的位置,如果刚好是第一个,则返回,否则一直查找到key相等的value并返回,如果还是没找到则分会null。 本文的目标是带着学习的态度,查看HashMap的源码,从put,get,resize三个方法分析它的内部实现。 HashMap数据结构 HashMap继承自AbstractMap<K,V>,实现了Map<K, V>接口(AbstractMap<K,V>也实现了这个接口,为什么没有冲突呢?): Map接口有一个Entry接口,HashMap中内部类Node实现了Entry接口,数据就存放在: Node < K , V > [ ] table ; HashMap内部定义了几个重要参数: // 加载因子默认是0.75,取值越小,hash冲突概率越低,插入和查找速度愈快,但是占用的空间更多 final float

Step By Step(C++模板重载和特化)

十年热恋 提交于 2020-02-06 05:44:13
一、模板函数重载: 函数重载是一个非常通用亦非常容易理解的编程基础概念,既函数名相同而函数签名不同的一组函数,在实际的调用中,编译器会根据函数参数的不同自动选择最为合适且最为特化的函数。在推演的过程中,如果出现多个函数均符合该调用规则,编译器将根据其内置的特化规则,选择最为特殊的函数作为候选函数。然而如果仍有多个候选函数的话,编译器将报出二义性错误。和普通函数一样,在C++中模板函数也同样支持函数重载的功能,甚至可以将模板函数与普通函数混合在一起,以达到更为灵活的函数重载的效果。 在这里,我们对于函数重载的概念本身将不再做过多的赘述了,而是将重点放在模板函数重载的应用场景和应用技巧上。下面我将给出一个利用模板函数重载计算哈希值的代码示例: 1 #include <stdio.h> 2 3 template<typename T> 4 int hash_code(T v) { 5 return v.hashCode() * 2; 6 } 7 8 template<typename T> 9 int hash_code(T* v) { 10 return v->hashCode(); 11 } 12 13 int hash_code(const int v) { 14 return v + 100; 15 } 16 17 class HashClass { 18 public: 19

Vue前端路由(Vue-router)

梦想的初衷 提交于 2020-02-06 00:59:50
1.路由的概念 路由的本质就是一种对应关系,比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址对应的资源。 那么url地址和真实的资源之间就有一种对应的关系,就是路由。 路由分为前端路由和后端路由 1).后端路由是由服务器端进行实现,并完成资源的分发 2).前端路由是依靠hash值(锚链接)的变化进行实现 后端路由性能相对前端路由来说较低,所以,我们接下来主要学习的是前端路由 前端路由的基本概念:根据不同的事件来显示不同的页面内容,即事件与事件处理函数之间的对应关系 前端路由主要做的事情就是监听事件并分发执行事件处理函数 2.前端路由的初体验 前端路由是基于hash值的变化进行实现的(比如点击页面中的菜单或者按钮改变URL的hash值,根据hash值的变化来控制组件的切换) 核心实现依靠一个事件,即监听hash值变化的事件 window.onhashchange = function(){ //location.hash可以获取到最新的hash值 location.hash } 前端路由实现tab栏切换: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial

Redis源码剖析 字典 结构 ( dict.h/dict.c)

≯℡__Kan透↙ 提交于 2020-02-04 20:09:29
字典又称为符号表、关联数组 、或者映射。是一种用于保存键值对(key-value)的抽象结构数组。 例如:Redis中所有key到value的映射,就是通过字典结构维护,还有hash类型的键值。 1、Redis中字典的实现 Redis的字典是由哈希表实现的,一个哈希表有多个节点,每个节点保存一个键值对。 1.1哈希表(dict.c/dict.h) typedef struct dictht{ dictEntry** table;//存放一个数组的地址,数组中存放哈希节点dictEntry的地址 unsingned long size;//哈希表table的大小,出始大小为4 unsingned long sizemask;//用于将hash值映射到table位置的索引,大小为(size-1) unsingned long used;//记录哈希表已有节点(键值对)的数量 }dictht; 1.2哈希表节点 typedef struct dictEntry{ void *key; //key union{ void* val; uint64_t u64; int64_t s64; double d; }v; //val struct dictEntry *next; //指向下一个节点,用来解决 哈希冲突 }dictEntry; 1.3字典 typedef struct dict{

【Redis源代码剖析】 - Redis内置数据结构之字典dict

雨燕双飞 提交于 2020-02-04 20:07:13
原创作品,转载请标明: http://blog.csdn.net/Xiejingfa/article/details/51018337 今天我们来讲讲Redis中的哈希表。 哈希表在C++中相应的是map数据结构。但在Redis中称作dict(字典)。Redis仅仅是用了几个简单的结构体和几种常见的哈希算法就实现了一个简单的相似高级语言中的map结构。以下我们来详细分析一下dict的实现。 在学习数据结构的时候。我们接触过一种称作“散列表”的结构,能够依据关键字而直接訪问记录。 说的详细一点就是通过把key值映射到表中的一个位置来訪问。从而加快查找速度。 Redis中的dict数据结构和我们之前学过的“散列表”大同小异。总结例如以下: 1、dict的结构 Redis定义了dictEntry、dictType、dictht和dict四个结构体来实现散列表的功能。它们详细定义例如以下: (1)dictEntry结构体 /* 保存键值(key - value)对的结构体,相似于STL的pair。*/ typedef struct dictEntry { // 关键字key定义 void *key; // 值value定义,仅仅能存放一个被选中的成员 union { void *val; uint64_t u64; int64_t s64; double d; } v; //

3.java中的数据结构

喜夏-厌秋 提交于 2020-02-04 18:09:12
java中关于数据结构的工具类,暂时就这么称呼吧,其实也贼拉多,害看图包 上面的图肯定时不全,知识一些常用的。简单看一下上面列举出来的“工具类”的源码和一些常见的面试问题: List接口中的“工具类”,是一个有序集合,可以重复。 ArrayList: 底层使用数组实现的,数据是有序数据(插入的顺序),具有索引查找比较快,线程不安全。 属性: //默认容量 private static final int DEFAULT_CAPACITY = 10; //空集合 private static final Object[] EMPTY_ELEMENTDATA = {}; //默认空集合 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //数据存储数组,不参与序列化 transient Object[] elementData; //容量 private int size; //最大容量 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 构造方法: /* *指定长度的构造方法 */ public ArrayList(int initialCapacity) { if (initialCapacity > 0) {

数据结构之HashMap详解(一)

醉酒当歌 提交于 2020-02-03 07:30:03
在之前有一篇博客介绍了HashMap, 数据结构之Hash表(哈希表) 现在对之前的内容做一个补充。 说HashMap之前,看下数组: 数组的优点在于查找速度快,每个区域都是紧挨着的,并且有下标,可以根据下标快速找到要查找的元素。 缺点:增删麻烦,如果在第二个元素后面再添加个元素的话,那么就需要重新建一个数组,填入对应的信息。 链表:每个内存除了存放自身的元素外,还保留下个内存区域的地址, 优点:插入新元素方便,只需要将指针指向新元素,新元素指向原来的下一个指针即可。 缺点:查找速度慢。链表不像数组那样有下标,链表查找元素只能从head结点开始,一个一个向下找。 而散列表则是综合了两者优点于一身的结构: 上面是数组,数组每个区域内是链表。 说到散列表,就应当说哈希,没有哈希,散列表就无法寻址找数据, 哈希 哈希:Hash也称散列、哈希,对应的英文都是Hash,基本原理就是把任意长度的输入,通过Hash算法变成固定长度的输出,这个映射的规则就是对应的Hash算法,而原始数据映射后的二进制串就是哈希值。 Hash特点: 1、hash值不可以反向推导出原始的数据 2、输入的数据的微小变化会得到完全不同的hash值,相同的数据可以得到相同的值。 3、哈希算法的执行效率要高效 4、hash算法的冲突概率要小 hash原理是将输入空间的值映射成hash空间内

剑指Offer(类库)——HashMap、HashTable、ConcurrentHashMap(上)

℡╲_俬逩灬. 提交于 2020-02-02 03:02:50
Map是由一对对的key-value组成的,key要求是唯一的,value不要求。 通过看源码可以得出:key自带去重功能是Set类型的,value是Collection接口可存放任意集合。 来看一下Map的实现类: HashMap、HashTable、ConcurrentHashMap之间的区别? HashMap JDK8之前HashMap是由数组+链表组成的,数组查找快增删慢,链表增删快查找慢,HashMap结合了两者的优势,HashMap不是线程安全的效率很高,组织键位如图: 没有给HashMap初始长度的时候 HashMap默认初始长度是16 ,初始长度16的数组中每个数组的位置存放的是 链表的头结点 ,可以通过模运算得到头结点的存放位置:hash(key.hashCode())%len,hashCode的运算本身是通过位运算得到的。 但是存在一种特殊情况,通过模运算得到的位置每次都是同一个这样的话就不断在一条链表中去插入, 最坏的情况是时间复杂度从O(1)变成O(n)。 JDK8之后对HashMap进行了优化,将原先的HashMap由 数组+链表 组成的道理变成了 数组+链表+红黑树 。 添加红黑树之后再次遇到特殊的情况时就可以使用 TREEIFY_THRESHOLD 去判断是否将链表转换成一颗红黑树,这种情况下 最坏的时间复杂度从O(n)变成O(nlogn)。

索引与优化

≡放荡痞女 提交于 2020-02-02 02:02:19
参考: http://blog.csdn.net/xluren/article/details/32746183 http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html 关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢。还是以WordPress来说,其多个数据表都会对经常被查询的字段添加索引,比如wp_comments表中针对5个字段设计了BTREE索引。 一个简单的对比测试 以我去年测试的数据作为一个简单示例,20多条数据源随机生成200万条数据,平均每条数据源都重复大概10万次,表结构比较简单,仅包含一个自增ID,一个char类型,一个text类型和一个int类型,单表2G大小,使用MyIASM引擎。开始测试未添加任何索引。 执行下面的SQL语句: 1 mysql> SELECT id,FROM_UNIXTIME( time ) FROM article WHERE a.title= '测试标题' 查询需要的时间非常恐怖的,如果加上联合查询和其他一些约束条件,数据库会疯狂的消耗内存

每天刷Web面试题(前10天汇总)

时间秒杀一切 提交于 2020-02-01 02:46:24
一、算法题部分 1. 如何获取浏览器URL中查询字符串中的参数? function getParamsWithUrl(url) { var args = url.split('?'); if (args[0] === url) { return ""; } var arr = args[1].split('&'); var obj = {}; for ( var i = 0; i < arr.length; i++) { var arg = arr[i].split('='); obj[arg[0]] = arg[1]; } return obj; } var href = getParamsWithUrl('http://www.itlike.com?id=1022&name=撩课&age=1'); console.log(href['name']); // 撩课 2. 写一个深度克隆方法(es5)? /** * 深拷贝 * @param {object}fromObj 拷贝的对象 * @param {object}toObj 目标对象 */function deepCopyObj2NewObj(fromObj, toObj) { for(var key in fromObj){ // 1. 取出键值对 var fromValue = fromObj[key]; // 2.