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>的继承体系也 ...
随机推荐
- Feign自定义重试策略及超时时间
背景 feign可以配置重试策略及超时时间,但是无法根据业务场景动态的设置.可能会引起接口幂等,无效重试资源耗费,大数据量耗时操作报超时异常等问题.所以需要更细粒度的重试策略及超时时间配置. 自定义重 ...
- Angular: 点击一次按钮,增加一个元素
解决方案 思路 在组件的typesscript文件中,创建一个数组来存储每个按钮的信息 在模板中使用 *ngFor 指令来循环渲染按钮列表 在按钮事件的处理函数中,每次点击按钮时向按钮数组添加一个新的 ...
- docker-run-failed
Phenomenon overlay2 not such file or directory. overlay2 not such file or directory. network not suc ...
- 【python】调用钉钉机器人发起通知
有时候需要做个某些服务的状态监控,用钉钉机器人发通知挺方便的.可以用shell脚本配合crontab检测状态,检测到异常就调用python脚本发起告警. python内容 此处用的python3,需要 ...
- 【技术积累】Linux中的命令行【理论篇】【七】
atrm命令 命令介绍 atrm命令是Linux系统中的一个命令行工具,用于取消或删除已经安排的at命令.at命令是一种用于在指定时间执行一次性任务的工具. 命令说明 atrm命令的语法如下: atr ...
- GC的前置工作,聊聊GC是如何快速枚举根节点的
本文已收录至GitHub,推荐阅读 Java随想录 微信公众号:Java随想录 原创不易,注重版权.转载请注明原作者和原文链接 目录 什么是根节点枚举 根节点枚举存在的问题 如何解决根节点枚举的问题 ...
- 当小白遇到FullGC
起初没有人在意这场GC,直到它影响到了每一天! 前言 本文记录了一次排查FullGC导致的TP99过高过程,介绍了一些排查时思路,线索以及工具的使用,希望能够帮助一些新手在排查问题没有很好的思路时,提 ...
- WPF MVVM之点滴分享
(第五点:绑定源有修改) 我并不打算长篇累牍的介绍什么是MVVM.我尽量简洁的介绍,并把自己的经验分享给大家. 一.关于MVVM M:Model,数据模型(后台存储数据的类) V:View,视图(大部 ...
- 例子:统计电影类型的个数,以及用bar绘制出来表示
import pandas as pdimport numpy as npfrom matplotlib import pyplot as plt#获取各种电影类型的数量file='./IMDB-Mo ...
- Record - Nov. 27st, 2020 - Exam. REC & SOL
Problem. 1 Junior - Thinking Desc. & Link. 注意到值域乘范围刚好能过. 然后就存两个桶即可...(数组开小飞了半天才调出来...) Problem. ...