C# Dictionary的底层实现解析
引用:
https://www.cnblogs.com/InCerry/p/10325290.html
字典原理分析:
1、用数组存元素,元素的结构体存hashCode、next、key、value。 初始化的时候该数组的长度和桶的长度都是size(后续存在remove操作,数组并不是一一对应字典元素)
2、add操作通过hash算法获得hashCode,求余获得桶位置。元素实体该赋值赋值,桶记录实体idx,如果桶冲突,利用实体的next用单链表解决。(链地址法)
3、remove操作,处理对应桶的链表,重置元素实体的各种字段。记录freeCount, count-freeCount==真实字典长度
4、其他细节:字典有个版本字段,增删改都会导致+1。(freeList;//记录最近一次remove的实体的idx)
private void Resize(int newSize, bool forceNewHashCodes) {
Contract.Assert(newSize >= entries.Length);
//创建新的桶数组
int[] newBuckets = new int[newSize];
for (int i = 0; i < newBuckets.Length; i++) newBuckets[i] = -1;
//创建新的实体数组
Entry[] newEntries = new Entry[newSize];
//拷贝实体数组
Array.Copy(entries, 0, newEntries, 0, count);
//强制重新计算hashCode
if(forceNewHashCodes) {
for (int i = 0; i < count; i++) {
if(newEntries[i].hashCode != -1) {
newEntries[i].hashCode = (comparer.GetHashCode(newEntries[i].key) & 0x7FFFFFFF);
}
}
}
for (int i = 0; i < count; i++) {
if (newEntries[i].hashCode >= 0) {
//当hashCode大于-1(该元素有值),赋值桶的值
int bucket = newEntries[i].hashCode % newSize;
newEntries[i].next = newBuckets[bucket];
newBuckets[bucket] = i;
}
}
buckets = newBuckets;
entries = newEntries;
}
Find操作
private int FindEntry(TKey key) {
...
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
//对应的桶拿到该桶位置最近一次的实体的idx, 遍历桶位置的单链表,如果对应的key和参数key相等,则return
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
}
...
return -1;
}
C# Dictionary的底层实现解析的更多相关文章
- ArrayList底层代码解析笔记
通过底层代码可以学习到很多东西: public class ArrayList<E> extends AbstractList<E> implements List<E& ...
- Spring Cloud底层原理解析
概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓 ...
- ArrayList 源码底层实现解析 基于1.8
ArrayList 介绍 ArrayList是一种线性数据结构,它的底层是用数组实现的,是动态数组.与Java中的数组相比,它的容量能动态增长.源代码里有解释.当创建一个数组的时候,就必须确定它的大小 ...
- git plumbing 更加底层命令解析-深入理解GIT
原文: http://rypress.com/tutorials/git/plumbing 本文详细介绍GIT Plumbing--更加底层的git命令,你将会对git在内部是如何管理和呈现一个项目r ...
- 利用Redisson实现分布式锁及其底层原理解析
Redis介绍 参考地址:https://blog.csdn.net/turbo_zone/article/details/83422215 redis是一个key-value存储系统.和Memcac ...
- LinkedList底层代码解析笔记
LinkedList是属于Sequence List,故遍历是用迭代器更快; LinkedList继承自AbstractSequenceList.实现了List及Deque接口.其实AbstractS ...
- python 集合(set)和字典(dictionary)的用法解析
Table of Contents generated with DocToc ditctaionary and set hash 介绍 集合-set 创建 操作和访问集合的元素 子集.超集.相对判断 ...
- git的核心命令使用和底层原理解析
文章目录: GIT体系概述 GIT 核心命令使用 GIT 底层原理 一.GIT体系概述 GIT 与 svn 主要区别: 存储方式不一样 使用方式不一样 管理模式不一样 1.存储方式区别 GIT把内容按 ...
- 从HBase底层原理解析HBASE列族不能设计太多的原因?
在之前的文章<深入探讨HBASE>中,笔者详细介绍了: HBase基础知识(包括简介.表结构).系统架构.数据存储 WAL log和HBase中LSM树的应用 HBase寻址机制 mino ...
随机推荐
- C/S C# WPF锐浪报表教程
前言:锐浪报表是一种中国式报表的报表开发工具.博主使用锐浪报表有一段时间了,积累了一些经验希望能帮助你快速掌握并使用 第一章:集成项目 首先我们先去锐浪报表官网下载并安装锐浪报表. 创建WPF应用程序 ...
- springboot集成jpa操作mybatis数据库
数据库如下 CREATE TABLE `jpa`.`Untitled` ( `cust_id` bigint() NOT NULL AUTO_INCREMENT, `cust_address` var ...
- android屏幕适配的全攻略2--支持手机各种屏幕密度dpi
如何为不同密度的屏幕提供不同的资源和使用密度独立的单位. 1 使用密度无关像素 坚决杜绝在布局文件中使用绝对像素来定位和设置大小.因为不同的屏幕有不同的像素密度,所以使用像素来设置控件大小是有问题的, ...
- 微信小程序 wx:if 多条件判断
<view wx:if="{{a}}">单个条件</view> <view wx:if="{{a || b}}">多个或条件 ...
- 暑假集训Day2 状压dp 特殊方格棋盘
首先声明 : 这是个很easy的题 可这和我会做有什么关系 题目大意: 在n*n的方格棋盘上放置n个车,某些格子不能放,求使它们不能互相攻击的方案总数. 注意:同一行或同一列只能有一个车,否则会相互攻 ...
- Oracel中coalesce函数的用法
1.coalesce函数的用法 1.1 取出第一个不为空的列的数据.
- caffe的python接口学习(4)mnist实例手写数字识别
以下主要是摘抄denny博文的内容,更多内容大家去看原作者吧 一 数据准备 准备训练集和测试集图片的列表清单; 二 导入caffe库,设定文件路径 # -*- coding: utf-8 -*- im ...
- egret的WebView实现
需求 在egret中嵌入网页,类似 . 网上大概有两种思路吧,一种是直接在body里面加入iframe,如:[Egret]里使用iframe标签达到内嵌多个web界面;另一种就是通过模仿htmlinp ...
- Java设计模式十九——责任链模式
责任链模式 老李的苦恼 每个人在出生的时候,都早已在暗中被标好了三六九等. 老李是一名建筑工地的木匠,和大多数生活在社会最底层的农民工一样,一辈子老实本分,胆小怕事.在他们的心中,谁当老爷都没有区别, ...
- 【贪心】Emergency Evacuation
题目 大致题意 把指定的人从同一出口送出车外,且同一位置不能同时有两个人,求所需的最短时间. 分析 第一感觉就是利用贪心思想解决问题,但是这道题的数据范围用模拟的话肯定是会爆掉的,所以这是不可取的.我 ...