我正在设计一个类库,它有一堆类型的方法"EnsureXXX".只要调用代码需要某些东西而不需要特定于参数的初始化,就会调用此方法的思想.它类似于EnsureChildControlsASP.Net 的方法,但有参数作为鉴别器.
例如:
public static class SomeUtilityClass {
public static void EnsureSomething(string arg1, int arg2, object arg3)
{
// Logic should be called once for each args combination
}
}
public class CallerClass
{
public void Foo()
{
SomeUtilityClass.EnsureSomething("mycustomerid", 4, myData.SomeProperty);
}
public void Foo2()
{
SomeUtilityClass.EnsureSomething("mycustomerid", 4, myData.SomeProperty);
}
}
Run Code Online (Sandbox Code Playgroud)
因为这样的模式将在几个地方重用并经常调用,所以我必须将性能作为目标.我还必须有一个线程安全的方法.
为此,我写了一个小实用程序类:
public sealed class CallHelper
{
private static readonly HashSet<int> g_YetCalled = new HashSet<int>();
private static readonly object g_SyncRoot = new object();
public static void EnsureOnce(Type …Run Code Online (Sandbox Code Playgroud) 我永远不需要将对象存储在哈希表中.原因有两个:
另一方面,Equals()操作是一种非常常用的功能.
因此我想知道在实现Equals函数(我经常需要)时是否有必要实现GetHashCode(我从不需要)?
我需要在GetHashCode中为BitArray生成快速哈希码.我有一个字典,其中键是BitArrays,所有BitArrays长度相同.
有没有人知道从可变位数生成良好哈希的快速方法,如在这种情况下?
更新:
我最初采用的方法是直接通过反射访问内部int数组(速度比这种情况下的封装更重要),然后对这些值进行异或.XOR方法似乎运行良好,即在"字典"中搜索时,我的"等于"方法不会过度调用:
public int GetHashCode(BitArray array)
{
int hash = 0;
foreach (int value in array.GetInternalValues())
{
hash ^= value;
}
return hash;
}
Run Code Online (Sandbox Code Playgroud)
但是,Mark Byers建议并在StackOverflow其他地方看到的方法稍好一些(对于我的测试数据,XOR为16570等于呼叫,而对于XOR为16608).请注意,此方法修复了前一个错误,其中超出位数组末尾的位可能会影响散列值.如果位数组的长度减少,则可能发生这种情况.
public int GetHashCode(BitArray array)
{
UInt32 hash = 17;
int bitsRemaining = array.Length;
foreach (int value in array.GetInternalValues())
{
UInt32 cleanValue = (UInt32)value;
if (bitsRemaining < 32)
{
//clear any bits that are beyond the end of the array
int bitsToWipe = 32 - bitsRemaining;
cleanValue <<= bitsToWipe;
cleanValue >>= bitsToWipe;
} …Run Code Online (Sandbox Code Playgroud) 我计划在数据库中存储数十万个URL。我的UrlInfo表中的每一行都是不可变的,其中URL本身是逻辑主键。由于URL可能相当长,因此我决定对URL进行哈希处理,以作为添加新行时查找可能匹配项的快速方法。哈希不是我真正的钥匙,只是一种快速查找可能匹配项的方法。另外,我在每个域中使用RegEx模式,该模式将URL的本质提取为可以与其他URL进行比较的内容。我也将RegEx的结果存储为哈希,并且不关心它是否会产生重复项。
直到我了解到C#的string.GetHashCode()方法(我一直在使用它来对事物进行哈希处理)之前,一切都进展顺利,并不能保证它在.Net实现中是唯一的。当我尝试将哈希函数从ASP.Net迁移到SQLServer CLR代码时,我注意到了这一点。该Web应用程序使用.Net 4.0,而我了解到,SQLServer 2008 R2使用.Net 3.5。他们为相同的字符串产生了单独的哈希结果,所以现在我需要摆脱使用string.GetHashCode()的原因,因为当我将应用程序升级到.Net的将来版本时,我不必担心这种变化。
所以,问题:
自从在数据库中存储哈希后,我的体系结构是否有气味?还有更好的方法吗?显然,微软不希望我存储哈希结果!
有人可以推荐一个好的C#替换算法来哈希字符串吗?我在这里看到了乔恩(Jon),但不完全确定如何修改以使其适用于字符串(使用ascii代码遍历每个字符?)。
有没有比使用散列算法更好的字符串压缩算法?
谢谢
令人敬畏的回应有很多。非常感谢你!!!
我有2 IList<T>个相同类型的对象ItemsDTO.我想从另一个列表中排除一个列表.然而,这对我来说似乎没有用,我想知道为什么?
IList<ItemsDTO> related = itemsbl.GetRelatedItems();
IList<ItemsDTO> relating = itemsbl.GetRelatingItems().Except(related).ToList();
Run Code Online (Sandbox Code Playgroud)
我正在尝试related从relating列表中删除项目.
本文的底部描述了如何使用GetOrAdd(如果我理解正确)可能导致损坏/意外结果.
喀嚓/
ConcurrentDictionary专为多线程场景而设计.您不必在代码中使用锁来添加或删除集合中的项.但是,一个线程始终可以检索一个值,而另一个线程可以通过为相同的键提供一个新值来立即更新该集合.
此外,尽管ConcurrentDictionary的所有方法都是线程安全的,但并非所有方法都是原子方法,特别是GetOrAdd和AddOrUpdate.传递给这些方法的用户委托是在字典的内部锁之外调用的.(这样做是为了防止未知代码阻塞所有线程.)因此,可能会发生以下事件序列:
1)threadA调用GetOrAdd,找不到任何项,并通过调用valueFactory委托创建一个新项添加到Add.
2)threadB同时调用GetOrAdd,调用其valueFactory委托,并在threadA之前到达内部锁,因此将其新的键值对添加到字典中.
3)threadA的用户委托完成,线程到达锁,但现在看到该项已经存在
4)threadA执行"Get",并返回先前由threadB添加的数据.
因此,无法保证GetOrAdd返回的数据与线程的valueFactory创建的数据相同.调用AddOrUpdate时,可能会发生类似的事件序列.
题
验证数据的正确方法是什么,并重试更新?一个很好的方法是根据旧值的内容尝试/重试此操作的扩展方法.
这将如何实施?我可以依赖result(verify)作为有效结束状态,还是必须使用不同的方法重试并重新检索值?
码
更新值时,以下代码具有竞争条件.期望的行为是AddOrUpdateWithoutRetrieving()将以不同的方式递增各种值(使用++或Interlocked.Increment()).
我还想在一个单元中执行多个字段操作,如果先前的更新由于竞争条件而没有"占用",则重试更新.
运行代码,您将看到控制台中出现的每个值开始增加1,但每个值都会漂移,有些值会前后几次迭代.
namespace DictionaryHowTo
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// The type of the Value to store in the dictionary:
class FilterConcurrentDuplicate
{
// Create a new concurrent dictionary.
readonly ConcurrentDictionary<int, TestData> eventLogCache =
new ConcurrentDictionary<int, TestData>();
static void Main()
{
FilterConcurrentDuplicate c = new FilterConcurrentDuplicate();
c.DoRace(null);
}
readonly …Run Code Online (Sandbox Code Playgroud) c# concurrency multithreading thread-safety task-parallel-library
这是一个学术观点,但我觉得如果我不理解为什么这会被诸如Effective Java和许多SO问题这样的书推荐,我不完全理解哈希码.
假设:
public sealed class Point
{
private readonly int x;
private readonly int y;
//constructor ommited
//equals ommited
public override int GetHashcode()
{
int hash = 17; //why should the initial value be non-zero?
unchecked
{
hash = hash * 31 + x; //do not tell me why I should use primes - that is not the question
hash = hash * 31 + y;
return hash;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,据推测,初始值的原因是它减少了其中一个组件为零的冲突.
我很想找到任何有帮助的例子.
这是一个碰撞的例子,但是初始值没有任何可能性.
x y Hash Without initial …Run Code Online (Sandbox Code Playgroud) 我一直在阅读这个有趣的话题(IMO).但我不完全明白一件事:
字典大小将其容量(加倍到最接近的素数)增加到素数(重新分配时):因为:
int index = hashCode % [Dictionary Capacity];
Run Code Online (Sandbox Code Playgroud)
[Dictionary Capacity]因为他们的GreatestCommonFactor 是1.这有助于避免碰撞.此外
我见过许多实施的样本GetHashCode():
以下是Jon Skeet的样本:
public override int GetHashCode()
{
unchecked
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
hash = hash * 23 + field3.GetHashCode();
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白:
题
难道素数使用 两种在:
Dictionary capacity与中产生 …
可以在类中使用GUID私有属性,以便在GetHashCode覆盖中使用它吗?
就像是:
public class Voucher : IComparable<Voucher>, IComparable, IEquatable<Voucher>
{
private Guid? _guid;
private Guid Guid
{
get
{
return _guid ?? (_guid = Guid.NewGuid()).GetValueOrDefault();
}
}
public int Id { get; private set; }
public string Number { get; private set; }
public DateTime Date { get; private set; }
public Voucher(string number, DateTime date)
{
Number = number;
Date = date;
}
public Voucher(int id, string number, DateTime date)
: this(number, date)
{
Id = id;
}
public …Run Code Online (Sandbox Code Playgroud) 帮助说:
匿名类型是直接从对象派生的类类型,不能转换为除object之外的任何类型.尽管您的应用程序无法访问它,但编译器为每个匿名类型提供了一个名称.从公共语言运行库的角度来看,匿名类型与任何其他引用类型没有区别.
如果程序集中的两个或多个匿名对象初始值设定项指定了具有相同顺序且具有相同名称和类型的属性序列,则编译器会将对象视为相同类型的实例.它们共享相同的编译器生成的类型信息.
因为匿名类型上的Equals和GetHashCode方法是根据属性的Equals和GetHashCode方法定义的,所以同一匿名类型的两个实例只有在它们的所有属性相等时才相等.
这些都是真的,但是怎么样?参考源明确显示了如何比较对象(ReferenceEquals)和"直接从对象派生"的类型不能具有此特殊行为.它不匹配的水煤浆Equals在ValueType任.
那怎么办?匿名类型如何覆盖Equals()并且GetHashCode()没有任何可见的覆盖?
c# ×10
gethashcode ×5
.net ×3
dictionary ×2
hash ×2
algorithm ×1
bitarray ×1
concurrency ×1
equals ×1
guid ×1
java ×1
linq ×1
math ×1
performance ×1
regex ×1
sql-server ×1