AddOrUpdate 不更新
AddOrUpdate not updating
我有一个<byte[], int>
类型的并发字典_dict
我遍历另一个字符串列表 (list1
) 的项目,如果该项目作为键存在于 _dict
中,我增加它的值;如果没有,我将它添加到 _dict
并将其值设置为 1
foreach(byte[] item in list1)
{
_dict.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
}
问题是,即使该项目已经存在于 _dict
,它会再次将其添加到 _dict
而不是更新它。
我的代码有什么问题?
更新代码块
internal class someClass
{
public List<byte[]> list1 { get; set; }
public ConcurrentDictionary<byte[], int> dict1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
someClass obj = new someClass();
if (obj.list1 != null && obj.list1.Count > 0)
{
foreach (byte[] item in obj.list1)
{
// upsert operation (add if string not in dictionary; update by incrementing count if it does exist)
obj.dict1.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
}
}
}
}
使用 byte[] 作为字典键是个坏主意,因为将通过引用而不是内部数据来比较两个不同的字节数组。所以,如果你强烈需要 byte[] 作为字典键,你应该为 IEqualityComparer 接口编写自己的 class 。例如:
public class ByteArrayComparer : IEqualityComparer<byte[]> {
public bool Equals(byte[] x, byte[] y) {
if ( x == null || x == null ) {
return x.length == y.length;
}
return x.SequenceEqual(y);
}
public int GetHashCode(byte[] key) {
return key.Sum(b => b);
}
}
由于您已将键类型从 string
更改为 byte[]
,现在您看到的行为是正确的(最初,问题包含 string
键)。
因为:
字典使用默认值 IEqualityComparer
比较键,在 byte[]
的情况下只是比较引用。
由于两个 byte[]
数组是两个不同的对象,即使它们包含相同的元素,它们也会被视为不同的键。
考虑自己创建一个 IEqualityComparer
实现并在此构造函数中使用它:
public ConcurrentDictionary(
IEqualityComparer<TKey> comparer
)
编辑:
这是一个工作示例:
public class ByteArrayComparer : IEqualityComparer<byte[]>
{
public bool Equals(byte[] x, byte[] y)
{
if (x == null || y == null)
return false;
if(x.Length != y.Length)
return false;
return x.SequenceEqual(y);
}
public int GetHashCode(byte[] array)
{
unchecked
{
return array.Aggregate(17, (v, b) => v * 23 + b.GetHashCode(), v => v);
}
}
}
internal class someClass
{
public List<byte[]> list1 = new List<byte[]>();
public ConcurrentDictionary<byte[], int> dict1 = new ConcurrentDictionary<byte[], int>(new ByteArrayComparer());
}
void Main()
{
someClass obj = new someClass();
obj.list1.Add(new byte[] { 1, 2 });
obj.list1.Add(new byte[] { 1, 2 });
obj.list1.Add(new byte[] { 1, 2 });
obj.list1.Add(new byte[] { 2, 3 });
obj.list1.Add(new byte[] { 2, 3 });
obj.list1.Add(new byte[] { 3, 4 });
if (obj.list1 != null && obj.list1.Count > 0)
{
foreach (byte[] item in obj.list1)
{
// upsert operation (add if string not in dictionary; update by incrementing count if it does exist)
obj.dict1.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
}
}
}
obj.dict1 的最终内容将是:
Key 01 02
Value 3
Key 02 03
Value 2
Key 03 04
Value 1
我有一个<byte[], int>
_dict
我遍历另一个字符串列表 (list1
) 的项目,如果该项目作为键存在于 _dict
中,我增加它的值;如果没有,我将它添加到 _dict
并将其值设置为 1
foreach(byte[] item in list1)
{
_dict.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
}
问题是,即使该项目已经存在于 _dict
,它会再次将其添加到 _dict
而不是更新它。
我的代码有什么问题?
更新代码块
internal class someClass
{
public List<byte[]> list1 { get; set; }
public ConcurrentDictionary<byte[], int> dict1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
someClass obj = new someClass();
if (obj.list1 != null && obj.list1.Count > 0)
{
foreach (byte[] item in obj.list1)
{
// upsert operation (add if string not in dictionary; update by incrementing count if it does exist)
obj.dict1.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
}
}
}
}
使用 byte[] 作为字典键是个坏主意,因为将通过引用而不是内部数据来比较两个不同的字节数组。所以,如果你强烈需要 byte[] 作为字典键,你应该为 IEqualityComparer 接口编写自己的 class 。例如:
public class ByteArrayComparer : IEqualityComparer<byte[]> {
public bool Equals(byte[] x, byte[] y) {
if ( x == null || x == null ) {
return x.length == y.length;
}
return x.SequenceEqual(y);
}
public int GetHashCode(byte[] key) {
return key.Sum(b => b);
}
}
由于您已将键类型从 string
更改为 byte[]
,现在您看到的行为是正确的(最初,问题包含 string
键)。
因为:
字典使用默认值 IEqualityComparer
比较键,在 byte[]
的情况下只是比较引用。
由于两个 byte[]
数组是两个不同的对象,即使它们包含相同的元素,它们也会被视为不同的键。
考虑自己创建一个 IEqualityComparer
实现并在此构造函数中使用它:
public ConcurrentDictionary(
IEqualityComparer<TKey> comparer
)
编辑: 这是一个工作示例:
public class ByteArrayComparer : IEqualityComparer<byte[]>
{
public bool Equals(byte[] x, byte[] y)
{
if (x == null || y == null)
return false;
if(x.Length != y.Length)
return false;
return x.SequenceEqual(y);
}
public int GetHashCode(byte[] array)
{
unchecked
{
return array.Aggregate(17, (v, b) => v * 23 + b.GetHashCode(), v => v);
}
}
}
internal class someClass
{
public List<byte[]> list1 = new List<byte[]>();
public ConcurrentDictionary<byte[], int> dict1 = new ConcurrentDictionary<byte[], int>(new ByteArrayComparer());
}
void Main()
{
someClass obj = new someClass();
obj.list1.Add(new byte[] { 1, 2 });
obj.list1.Add(new byte[] { 1, 2 });
obj.list1.Add(new byte[] { 1, 2 });
obj.list1.Add(new byte[] { 2, 3 });
obj.list1.Add(new byte[] { 2, 3 });
obj.list1.Add(new byte[] { 3, 4 });
if (obj.list1 != null && obj.list1.Count > 0)
{
foreach (byte[] item in obj.list1)
{
// upsert operation (add if string not in dictionary; update by incrementing count if it does exist)
obj.dict1.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
}
}
}
obj.dict1 的最终内容将是:
Key 01 02
Value 3
Key 02 03
Value 2
Key 03 04
Value 1