CoreFX中Dictionary<TKey, TValue>的源码解读
1 Dictionary<int, string> openWith = new Dictionary<int, string>();
2 openWith.Add(1000, "key值为1000");
3 openWith.Add(1001, "key值为1001");
1 public Dictionary(int capacity, IEqualityComparer<TKey>? comparer)
2 {
3 if (capacity > 0) Initialize(capacity);
4 if (!typeof(TKey).IsValueType)
5 {
6 _comparer = comparer ?? EqualityComparer<TKey>.Default;
7 if (typeof(TKey) == typeof(string) && NonRandomizedStringEqualityComparer.GetStringComparer(_comparer!) is IEqualityComparer<string> stringComparer)
9 {
10 _comparer = (IEqualityComparer<TKey>)stringComparer;
11 }
12 }
13 else if (comparer is not null && comparer != EqualityComparer<TKey>.Default)
14 {
15 _comparer = comparer;
16 }
17 }
1 private int Initialize(int capacity)
2 {
3 int size = HashHelpers.GetPrime(capacity);
4 int[] buckets = new int[size];
5 Entry[] entries = new Entry[size];
6 _freeList = -1;
7 #if TARGET_64BIT
8 _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size);
9 #endif
10 _buckets = buckets;
11 _entries = entries;
12 return size;
13 }
1 public static int GetPrime(int min)
2 {
3 foreach (int prime in Primes)
4 {
5 if (prime >= min) return prime;
6 for (int i = (min | 1); i < int.MaxValue; i += 2)
7 {
8 if (IsPrime(i) && ((i - 1) % HashPrime != 0)) return i;
9 }
10 return min;
11 }
12 }
1 internal static ReadOnlySpan<int> Primes => new int[]
2 {
3 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
4 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
5 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
6 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
7 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369
8 };
public static ulong GetFastModMultiplier(uint divisor) => ulong.MaxValue / divisor + 1;
1 private struct Entry
2 {
3 public uint hashCode;
4 public int next;
5 public TKey key;
6 public TValue value;
7 }
1 private ref int GetBucket(uint hashCode)
2 {
3 int[] buckets = _buckets!;
4 #if TARGET_64BIT
5 return ref buckets[HashHelpers.FastMod(hashCode, (uint)buckets.Length, _fastModMultiplier)];
6 #else
7 return ref buckets[(uint)hashCode % buckets.Length];
8 #endif
9 }
private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
{
Entry[]? entries = _entries;
uint hashCode = (uint) key.GetHashCode() ;
uint collisionCount = 0;
ref int bucket = ref GetBucket(hashCode);
int i = bucket - 1;
int index;
if (_freeCount > 0)
{
index = _freeList;
_freeList = StartOfFreeList - entries[_freeList].next;
_freeCount--;
}
else
{
int count = _count;
if (count == entries.Length)
{
Resize();
bucket = ref GetBucket(hashCode);
}
index = count;
_count = count + 1;
entries = _entries;
} ref Entry entry = ref entries![index];
entry.hashCode = hashCode;
entry.next = bucket - 1;
entry.key = key;
entry.value = value;
bucket = index + 1;
_version++; return true;
}
1 private void Resize() => Resize(HashHelpers.ExpandPrime(_count), false);
2
3 private void Resize(int newSize, bool forceNewHashCodes)
4 {
5 Entry[] entries = new Entry[newSize];
6 int count = _count;
7 Array.Copy(_entries, entries, count);
8 _buckets = new int[newSize];
9 #if TARGET_64BIT
10 _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize);
11 #endif
12 for (int i = 0; i < count; i++)
13 {
14 if (entries[i].next >= -1)
15 {
16 ref int bucket = ref GetBucket(entries[i].hashCode);
17 entries[i].next = bucket - 1;
18 bucket = i + 1;
19 }
20 }
21 _entries = entries;
22 }
1 public static int ExpandPrime(int oldSize)
2 {
3 int newSize = 2 * oldSize;
4 if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize) return MaxPrimeArrayLength;
5 return GetPrime(newSize);
6 }
1 internal ref TValue FindValue(TKey key)
2 {
3 ref Entry entry = ref Unsafe.NullRef<Entry>();
4 if (_buckets != null)
5 {
6 uint hashCode = (uint)key.GetHashCode();
7 int i = GetBucket(hashCode);
8 Entry[]? entries = _entries;
9 uint collisionCount = 0;
10 i--;
11 do
12 {
13 if ((uint)i >= (uint)entries.Length)
14 {
15 goto ReturnNotFound;
16 }
17 entry = ref entries[i];
18 if (entry.hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entry.key, key))
19 {
20 goto ReturnFound;
21 }
22 i = entry.next;
23 collisionCount++;
24 } while (collisionCount <= (uint)entries.Length);
25 goto ConcurrentOperation;
26 }
27 goto ReturnNotFound;
28 ConcurrentOperation:
29 ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
30 ReturnFound:
31 ref TValue value = ref entry.value;
32 Return:
33 return ref value;
34 ReturnNotFound:
35 value = ref Unsafe.NullRef<TValue>();
36 goto Return;
37 }
CoreFX中Dictionary<TKey, TValue>的源码解读的更多相关文章
- .NET中Dictionary<TKey, TValue>浅析
.NET中Dictionary<TKey, Tvalue>是非常常用的key-value的数据结构,也就是其实就是传说中的哈希表..NET中还有一个叫做Hashtable的类型,两个类型都 ...
- go 中 sort 如何排序,源码解读
sort 包源码解读 前言 如何使用 基本数据类型切片的排序 自定义 Less 排序比较器 自定义数据结构的排序 分析下源码 不稳定排序 稳定排序 查找 Interface 总结 参考 sort 包源 ...
- C#中Dictionary<TKey,TValue>排序方式
自定义类: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sy ...
- Twitter Storm中Bolt消息传递路径之源码解读
本文初次发表于storm-cn的google groups中,现以blog的方式再次发表,表明本人徽沪一郎确实读过这些代码,:). Bolt作为task被executor执行,而executor是一个 ...
- Spark-1.6.0中的Sort Based Shuffle源码解读
从Spark-1.2.0开始,Spark的Shuffle由Hash Based Shuffle升级成了Sort Based Shuffle.即Spark.shuffle.manager从Hash换成了 ...
- springBoot 日志中关于profiles设置的源码解读
在启动SpringBoot应用是看到到如下日志,于是出于好奇查看了下源代码: 首先,StartpInfoLogger类,采用jcl-over-slf4j[即Apache Common Log]中的Lo ...
- .net源码分析 – Dictionary<TKey, TValue>
接上篇:.net源码分析 – List<T> Dictionary<TKey, TValue>源码地址:https://github.com/dotnet/corefx/blo ...
- C# .Net 中字典Dictionary<TKey,TValue>泛型类 学习浅谈
一.综述: Dictionary<TKey,TValue>是在 .NET Framework 2.0 版中是新增的.表示键值对的集合,Dictionary<TKey,TValue&g ...
- C#中数组、集合(ArrayList)、泛型集合List<T>、字典(dictionary<TKey,TValue>)全面对比
C#中数组.集合(ArrayList).泛型集合List<T>.字典(dictionary<TKey,TValue>)全面对比 为什么把这4个东西放在一起来说,因为c#中的这4 ...
- c# 图解泛型List<T>, HashTable和Dictionary<TKey,TValue>
前辈在代码中使用了HashTable,由于我用的比较少,不能理解,为什么不用Dictionary?看了源码以及查阅资料,总结如下: 首先看看它们的继承体系: 我把list<T>的继承体系也 ...
随机推荐
- 2021-7-11 Vue的自定义指令简单实例
获取焦点简单实例,用Vue.directive(ps:指令)定义,命名不要是关键字,用v-加自定义指令名称调用,而内部用钩子函数inserted来实现 <!DOCTYPE html> &l ...
- 新一代开源流数据湖平台Apache Paimon入门实操-上
@ 目录 概述 定义 核心功能 适用场景 架构原理 总体架构 统一存储 基本概念 文件布局 部署 环境准备 环境部署 实战 Catalog 文件系统 Hive Catalog 创建表 创建Catalo ...
- 规范代码编写风格就用 eslint 和 prettier
eslint 可以用于规范我们的编码,使得项目中的代码风格一致,更利于阅读和维护,而 prettier 可以在当我们代码不符合 eslint 规范是进行部分自动修复. eslint 通过 npm in ...
- Hadoop集群启动没有DataNode进程
问题状况: 问题原因: 在启动Hadoop之前,进行了多次格式化,导致DataNode的ID发生了变化 解决方案: 我们可以删除从节点所有的DataNode资料,并重新格式化 解决流程 1.根据cor ...
- nginx配置gzip压缩
前言 为提高用户获取响应数据的速度,Nginx服务器可以将响应数据进行gzip压缩,在减小响应数据的大小后再发送给用户端浏览器. 要想启用gzip压缩,需要浏览器支持gzip压缩功能,目前大多数浏览器 ...
- JS标识符
什么是标识符? 变量名 函数名 属性名都称为标识符. 定义标识符规范如下 1) 标识符只能由字母 数字 下划线 $组成. 2) 标识符不能以数字开头,例如: 1name. 3) 标识符不能实JS中的关 ...
- AVR汇编(七):位操作和MCU控制指令
AVR汇编(七):位操作和MCU控制指令 位操作指令 SBI / CBI SBI 指令用于设置I/O寄存器中的第 b 位, CBI 指令用于清除I/O寄存器中的第 b 位. 例如: SBI DDRB, ...
- 【Hexo】NexT 主题的配置使用记录
目录 简介 版本 安装 配置记录 风格/主题 网页图标 菜单栏 侧边栏 本地搜索 代码块 动画效果 阅读进度 书签 Mermaid lazyload fancybox pangu 捐赠 版权声明 不蒜 ...
- 手机用户的开源福音「GitHub 热点速览」
不知道多少用安卓机的小伙伴,被开屏广告烦过.相比有些克制的 iOS 机,安卓机是个应用基本上都有开屏广告,少则 3s 多则 10s,本周获得 1k+ star 的 Android-Touch-Help ...
- Nexus搭建maven仓库并使用
一.基本介绍 参考:https://www.hangge.com/blog/cache/detail_2844.html https://blog.csdn.net/zhuguanbo/article ...